API pipeline: Link two cards with a relation
Index: API pipelines — index
Goal: link two cards with a named relation ("supplies", "works with", "part of") and read a card's relations and other edges.
A relation is an edge source → target labelled by a rubric (rel). The rubric's title reads the edge forward, its inverse_title backward; directed: false marks a symmetric label. Rubrics: API pipeline: Tag cards with rubrics
Steps
1. Pick or create the label. Any rubric you can read. Your own:
POST /v0/my/rubrics
Idempotency-Key: rel-label-1
{"title": "supplies", "inverse_title": "is supplied by"}
→ {"nonce": "470000000000000090", "card_type": "rubric", …}
2. Link.
POST /v0/my/relations
Idempotency-Key: rel-5c0e…
{"source": "470000000000000001", "target": "470000000000000002", "rel": "470000000000000090"}
→ {"created": true,
"relation": {"nonce": "470000000000000095", "rel": "470000000000000090",
"source_nonce": "470000000000000001", "target_nonce": "470000000000000002",
"direction": "out", "directed": true, "title": "supplies", "inverse_title": "is supplied by",
"label": "supplies", "mine": true, "created_at": "…",
"card": {"card_type": "project", "nonce": "470000000000000002", "title": "…", …}}}
- You need write on
source;targetandrelonly need to be readable. - The same source, target and rel again answers the existing edge with
"created": false.
3. Read a card's relations.
GET /v0/graph/relations?card=470000000000000002&dir=both&limit=50
→ {"relations": [{"nonce": "470000000000000095", "direction": "in", "label": "is supplied by", "card": {…the other card…}, …}],
"next_before": null}
card(required): the card whose relations you want.dir:out,inorboth(default).rel: one label only.limit: default 50, max 200. Next page:before=<next_before>.- Newest first. Only relations whose both cards and label you may see are returned; anonymous callers see public ones.
labelis the title in the direction you read;minemarks edges you created.
4. Remove. DELETE /v0/my/relations/{relation nonce} → 204. Allowed for the edge's author, or a writer of the source who can see the edge.
Other edges of your cards
GET /v0/graph/my/edges?kind=mention&target_nonce=470000000000000002&limit=100
→ {"edges": [{"kind": "mention", "source_type": "article", "source_nonce": "…", "target_nonce": "470000000000000002", …}], "total": 3}
kind(required):containment(workspace → card),mention(a card's text links another),anchor(card → its project),rubric(rubric tree),tag(card → rubric).- One of
source_nonce/target_nonceis required;source_type,target_type,fieldnarrow it;limit1–500 (default 100),offset. - Lists edges of your own cards. A card page (
GET /v0/my/<type>/{nonce}) already carries itsmentionedandcontainedcards.
Behind
- Nothing asynchronous: a relation exists as soon as the call answers.
Rules
- 400:
source must be a numeric nonce(same fortarget,rel),source and target must differ, missing Idempotency-Key;dir must be out|in|both. - 404: source not writable for you, target or rel not readable, or rel is not a rubric.
/v0/graph/my/edges: 400 for an unknownkind,source_nonce or target_nonce is required.
API surface
| Endpoint | Purpose | FE | AI / oracle |
|---|---|---|---|
POST /v0/my/relations |
Link two cards | no | yes |
DELETE /v0/my/relations/{nonce} |
Remove a relation | no | yes |
GET /v0/graph/relations?card= |
A card's relations | no | yes |
GET /v0/graph/my/edges?kind= |
Edges of your cards by kind | no | yes |