Browse documentationPagination

Protocol

Cursors are positions, not page numbers

When an endpoint declares pagination, pass its returned cursor back unchanged. Do not decode it, increment it, compare it lexically, or reuse it with different filters.

Collections can change

New rows may arrive while a client walks a collection. Process items by their stable identity and make downstream writes idempotent so a repeated item is harmless. An empty page with nextCursor: null ends the traversal; a client-side item count does not.

Every browsable collection returns { items, nextCursor }. A null cursor completes the walk; otherwise pass the opaque cursor to the same endpoint with the same filters and subject. Page-level facts, when a collection has any, live in its typed meta object rather than changing the envelope. Older endpoint-specific keys such as entries, events, or seenBy are not aliases and fail schema validation.

Every collection's generated endpoint reference includes the shared invalid_cursor refusal beside any operation-specific errors. The registry composes that common contract, so a newly registered collection cannot silently omit the cursor failure from its public documentation.

An empty page can still carry a continuation, so keep walking until nextCursor is null. Stop if an endpoint returns a cursor the same walk already requested: the response is not making progress. The shared iterateCollectionPages helper enforces both rules without imposing a product-wide page ceiling.

Bound every walk

Set a page limit the endpoint accepts, cap total work for interactive requests, and resume large background jobs from the last committed cursor. Query and response schemas appear in each endpoint's contract panel.