API pipeline: Search the graph
Index: API pipelines — index
Goal: find cards by keywords or by meaning, narrowed by card type, rubric, country, place and distance; or jump straight to a card by its link, @handle or nonce.
No token needed for public results; with a token you also get what is visible to signed-in people and what was shared with you.
Steps
- Search.
POST /v0/search/graph
{"query": "bike repair", "card_type": "project", "page": 1, "limit": 20,
"filters": {"exclude_terms": ["casino"]}}
→ {"hits": [{"card_type": "project", "nonce": "470000000000000001", "title": "…", "snippet": "…",
"rubrics": […], "location": {"nonce": "…", "title": "Lisbon", "geo": {"lat": 38.72, "lon": -9.14}}, …}],
"total_hits": 101, "page": 1, "total_pages": 6}
/v0/search/graphblends keywords and meaning (the default engine);/v0/search/graph/keywordmatches words only;/v0/search/graph/vectormatches meaning only. Same body, same answer.queryis clipped to 200 characters; it may be empty when a filter orcard_typenarrows the search.pagestarts at 1;limit1–100 (default 20).card_type:project,article,post,telegram_group,agenda,board,doc,sheet,rubric,workspace, …card_types: several types at once, any of them matches, e.g.["project", "article"]; can be combined withcard_type.- Rubric hits carry
can_markfor signed-in callers: whether you may tag cards with that rubric: API pipeline: Tag cards with rubrics, section B3.
- Narrow with
filters.
| Key | Value | Effect |
|---|---|---|
rubrics |
[["<a>", "<b>"], ["<c>"]] |
any inside a group, every group must match |
rubrics_not |
["<rubric>"] |
drop cards with these rubrics |
locations |
["<place nonce>"] |
only cards in that place or anywhere inside it |
preference_countries |
["<country place nonce>"] |
ranks those countries first, hides nothing |
preference_city + radius_km |
{"nonce": "<place>", "lat": 41.26, "lon": 69.22}, 50 |
ranks the nearest first (default radius 50 km), hides nothing |
exclude_terms |
["casino", "crypto"] |
hide cards containing any of these words |
kind |
"tag" or "place" |
with card_type: "rubric": topics or places only |
Rubric and place nonces: search {"query": "dentist", "card_type": "rubric", "filters": {"kind": "tag"}}; places by city or country name: API pipeline: Submit your Telegram groups, find groups by keyword, place or rubric, vet them and attach them to a campaign (part B).
Search inside a workspace: add
"workspace": "<workspace nonce>".Jump to a card by reference.
GET /v0/graph/resolve/@example-handle
→ {"card_type": "project", "nonce": "470000000000000001", "handle": "example-handle", "title": "…", "kind": null}
Takes a nonce, @handle or a bare handle; a handle that was renamed still resolves. Then open it with GET /v0/graph/{type}s/{nonce}.
- Pick among your own cards (token needed):
GET /v0/accessible/cards?type=project&type=workspace&q=trip&limit=30
→ {"items": [{"nonce": "…", "card_type": "workspace", "title": "Trip ideas", "source": "owned",
"permissions": {"read": true, "write": true, "execute": true}, "snippet": "…", …}],
"next_cursor": "…"}
Cards you own plus cards shared with you, with your rights on each. q matches titles in every language and handles; a nonce, @handle or https://cabi.chat/… link in q puts that exact card first. type is required (repeat it or comma-separate, up to 20); limit up to 100; page with cursor=<next_cursor> until it is null.
Rules
- 400
unknown filter: <key>,malformed filter: <key>,filters must be an object,workspace must be a nonce,workspace not found. resolve: 404 when unknown or not visible to you.accessible/cards: 400type is required,bad card type: …,bad cursor; 401 without a token.
API surface
| Endpoint | Purpose | FE | AI / oracle |
|---|---|---|---|
POST /v0/search/graph |
Keywords and meaning blended | yes (default) | yes |
POST /v0/search/graph/keyword |
Keywords only | yes | yes |
POST /v0/search/graph/vector |
Meaning only | yes | yes |
GET /v0/graph/resolve/{ident} |
Card by nonce or handle | yes (pasted links) | yes |
GET /v0/accessible/cards |
Your own and shared cards by title | yes (pickers) | yes |