API pipeline: Tag cards with rubrics
Index: API pipelines — index
Goal: tag your cards with rubrics, build your own rubric tree, and browse the public rubrics.
A rubric is a card (card_type: rubric). Kind tag classifies cards; kind place is a geographic node (rub.geo-…) and is set as a card's location, never as a tag. Rubrics form trees: a rubric contains its sub-rubrics, in order.
A. Browse public rubrics
1. Roots.
POST /v0/search/graph/keyword
{"query": "", "card_type": "rubric", "filters": {"roots_only": true}, "limit": 50}
→ {"hits": [{"card_type": "rubric", "nonce": "447697459225821184", "handle": "rub.iab", "title": "IAB Taxonomies", "kind": "tag", …},
{"nonce": "447799256720343040", "handle": "rub.isic", "title": "International Standard Industrial Classification (ISIC Rev.4)", …}, …]}
2. Children.
GET /v0/graph/rubrics/@rub.iab?contained_limit=200&contained_offset=0
→ {"nonce": "447697459225821184", "kind": "tag",
"contained": [{"card_type": "rubric", "nonce": "…", "title": "Automotive"}, …],
"contained_next_offset": 200}
Page with contained_offset until contained_next_offset is null. Find a rubric by word: {"query": "dental", "card_type": "rubric", "filters": {"kind": "tag"}} on the same search.
3. Cards under a rubric. Search with a rubric filter: "filters": {"rubrics": [["<rubric nonce>"]]} (inner lists OR, outer AND; rubrics_not excludes).
B. Tag a card
Rubrics are a field of the card. Send the whole list on create or PATCH; it replaces the previous one. Each rubric the new list adds needs the right to mark with it (B3); rubrics the card already has stay.
PATCH /v0/my/articles/470000000000000042
{"rubrics": ["<rubric nonce>", "470000000000000077"], "location": "<place nonce>"}
- Cards that take rubrics: project, article, post, board, doc, sheet, workspace, coupon, room.
primary_rubrics(optional): the ones shown first; at most 2 per tree. Without it the first ones of each tree are primary.location: one place rubric;""clears it. Find it withGET /v0/search/geo/cities?q=…, thenGET /v0/graph/resolve/@rub.geo-<geonameid>.rubrics: []removes all tags.
B2. Mark a card: add and remove in one call
Change some rubrics of a card without resending the whole list.
PATCH /v0/my/cards/470000000000000042/rubrics
{"add": ["470000000000000081"], "remove": ["470000000000000090"]}
→ {"nonce": "470000000000000042", "card_type": "article",
"rubrics": ["470000000000000081", "…"], "added": ["470000000000000081"],
"removed": ["470000000000000079", "470000000000000090"],
"transitions": [{"parent": "470000000000000078", "from": "470000000000000079", "to": "470000000000000081"}]}
- Works on any card that takes rubrics, if you may edit the card. Rubrics you do not list stay as they are.
- The answer shows only rubrics you can read.
Stage trees. Set exclusive_children: true on a rubric of yours (on create or PATCH) and it takes one child at a time on a card: adding a child replaces the sibling the card had. Use it for stages, e.g. New → Contacted → Won: one call per move, jumps allowed. transitions lists each move per tree (from: null: the card entered the tree; to: null: it left it).
History. Every mark is recorded as a change: what was added and removed, the stage moves, who made it and when.
B3. Who may mark with a rubric
Adding a rubric to a card needs the right to mark with that rubric. Removing a rubric never does.
- Your own rubrics: you may always mark with them.
- Someone else's rubric: you may mark with it when it is open for marking (its own execute permission, for everyone who can read it), or when its owner shared it with you with execute, by a grant or an access link issued on that rubric itself. Access to a parent rubric or to a workspace above it does not count: each rubric decides for itself. The shared public taxonomies are open for marking.
- New rubrics start closed (execute off): only you mark with them. To open one for everyone who can read it:
PATCH /v0/my/rubrics/{nonce} {"permissions": {"read": true, "write": false, "execute": true}}(an Unlisted or Public rubric; a Private one stays yours alone). To open it for chosen people or agendas, share it with execute: API pipeline: Share cards through access links - Only what a change adds is checked. Rubrics already on a card stay when you save the card again. The same right is needed for a new
locationand for the parent when you file a rubric under it. can_mark(true/false, signed-in callers only) tells you before you try: on a rubric's page (GET /v0/graph/rubrics/{nonce}and the rubrics in itscontained), on rubric hits of search, and on rubric rows ofGET /v0/accessible/cards?type=rubric. Pick rubrics withcan_mark: true; adding another one answers 403.- Oracles and agendas mark only with rubrics the agenda itself may mark with; your own right is not lent to them: API pipeline: Write an agenda for your oracles
C. Your own rubric tree
1. Create.
POST /v0/my/rubrics
Idempotency-Key: rub-1f3a…
{"title": "Wedding services", "content": "What we offer for weddings.", "language": "en",
"parent": "470000000000000070"}
→ {"nonce": "470000000000000077", "card_type": "rubric", "kind": "tag", "visibility": "Private", …}
- Only
titleis required.parent: a rubric you can write and may mark with (B3); the new one is filed under it. - A new rubric is closed for marking: only you mark cards with it until you open it or share it (B3).
visibility(+permissions,publicity) can be set on create; Unlisted and Public needproject(one of yours).kind: "place"is for geographic nodes and needsgeo {lat, lon}, alocationand Public for Everyone; you will rarely need it.directed: falseandinverse_titledescribe the rubric when it is used as a relation label: API pipeline: Link two cards with a relationexclusive_children: true: the rubric takes one child at a time on a card (stage trees, see B2).
2. Add, remove, reorder sub-rubrics.
POST /v0/my/rubrics/{rubric}/{child rubric} {"seqnum": 3} → 204 (seqnum optional: default = last)
PATCH /v0/my/rubrics/{rubric}/{child rubric} {"seqnum": 0} → 204 (move)
DELETE /v0/my/rubrics/{rubric}/{child rubric} → 204
Both must be rubrics you can write, and filing also needs the right to mark with the parent (B3); a cycle is refused. Other cards are not filed this way: they carry rubrics in their own rubrics field (B).
3. Edit, delete. PATCH /v0/my/rubrics/{nonce} (title, content, handle, visibility, project, …); DELETE /v0/my/rubrics/{nonce}. Yours: GET /v0/my/rubrics, GET /v0/my/rubrics/{nonce}.
Behind
- Nothing runs later: tags and location are stored with the card on save and are what the search filters match.
Rules (400)
at most 20 rubrics per card;rubric <n> listed twice;rubric <n> not found;rubric <n> is not readable;rubric <n> is a place; set it as location;rubric <n> is under another listed rubric(list the most specific one only);at most 2 primary rubrics per taxonomy root (…).- Tree:
a rubric cannot be its own parent,would create a cycle,parent must be numeric; a rubric you cannot write: 404. kind must be tag|place; a place still used as a location cannot be deleted or turned into a tag:<n> cards use this place as their location.- Marking (B2):
rubric <n> is both in add and remove;rubrics <a> and <b> are both under <parent>, which takes one child at a time: add one; the other rubric reasons as in B. A card you can read but not edit: 403; a card changed at the same moment: 409, retry. - Adding a rubric you may not mark with (on a card, as a location or as a parent): 403; see B3.
API surface
| Endpoint | Purpose | FE | AI / oracle |
|---|---|---|---|
POST /v0/search/graph/keyword (card_type: rubric) |
Find roots and rubrics | yes | yes |
GET /v0/graph/rubrics, GET /v0/graph/rubrics/{nonce} |
Public rubrics, a rubric's children | yes | yes |
rubrics, primary_rubrics, location on a card create / PATCH |
Tag a card | yes | yes |
POST /v0/my/rubrics, PATCH/DELETE /v0/my/rubrics/{nonce} |
Your rubrics | no | yes |
POST/PATCH/DELETE /v0/my/rubrics/{nonce}/{child} |
File, move, remove sub-rubrics | no | yes |
GET /v0/my/rubrics, GET /v0/my/rubrics/{nonce} |
Yours | no | yes |
PATCH /v0/my/cards/{nonce}/rubrics |
Add / remove rubrics in one call; stage moves | no | yes |