/api prefix (no v1).
Saving an item
Send the content node’s ID in the request body:201 with the saved_items resource:
201 with the original row — the created_at date and list position are not changed. No duplicate event is emitted. This makes double-taps from the UI safe to retry.
Access-gated. You can only save a node you can currently open. If the node is missing or the member does not have access, the API returns 404 — the same response for both cases, so no information about whether the node exists leaks.
Unsaving an item
204 always. Unsaving a node that was never saved is not an error.
The path parameter is the content_node_id, not the saved_items row ID.
Retrieving the list
content_nodes resources in the top-level included array so the frontend can render cards without additional fetches:
page[size] (1–100, default 20) and page[after] (cursor from the previous response’s links.next). See pagination for details.
Access behavior
Items whose access has been revoked are hidden from the list — they do not appear but are not deleted. If the member’s access is restored, the item reappears with its original save date. This means saving a node during a subscription and then losing access does not silently discard the bookmark; it comes back exactly where it was when the subscription renews. Consequently, the list length may be shorter thanpage[size] even when has_more is true — the cursor still advances correctly past hidden items.
is_saved on content reads
The portal content routes include an is_saved boolean on every content_nodes resource so the UI can show the bookmark state inline without a separate request:
is_saved is false for unauthenticated requests.
Auth and rate limits
All three endpoints require a contact JWT (hub member). Anonymous requests return401. A non-member returns 403.
| Route | Rate limit |
|---|---|
POST and DELETE | 120 requests / hour |
GET | 300 requests / hour |