Pagination
Read long lists one page at a time with continuation tokens and cursors.
Long lists come back one page at a time. Send the continuation value from each response with your next request, and stop only when a response has none, because a page can be empty and still have more after it. The Catalog and Applications use opaque page tokens; other services use one of two older styles, described below.
Page tokens on /api routes
Paginated operations of the Catalog and Applications take two optional request fields and return one optional response field:
| Field | Direction | Meaning |
|---|---|---|
pageSize | Request | The maximum number of entries in the page. |
pageToken | Request | The continuation from the previous page. Omit it for the first page. |
nextPageToken | Response | The continuation for the next page. Absent or null on the last page. |
The fields are in the query string of a GET operation, and in the JSON body
of a POST operation. For example, list the branches of a Project:
curl "https://api.spiraldb.dev/api/catalog/projects/$PROJECT_ID/branches?pageSize=100" \
-H "Authorization: Bearer $SPIRAL_TOKEN"Follow these rules:
- Treat a page size as a maximum. A page can contain fewer entries, or no
entries, and still have a
nextPageToken. Only an absent token ends the list. - Treat tokens as opaque. Do not decode, change, or construct a token.
- Keep the other parameters. Send the same filters and page size with each token. A token is bound to the operation, the Project, the filters, the page size, and the caller's authorization scope.
- Start again after a token error. The service returns an
INVALID_ARGUMENTerror for a malformed, expired, or mismatched token. It does not restart the list for you.
The service checks authorization again for each page, so a token never grants access on its own.
The Catalog validates pageSize from 1 to 1000, and uses 100 when you omit it.
Other services state their range in their reference.
Snapshot and live lists
Each paginated operation states its consistency in its reference:
- Snapshot lists read one immutable Project commit, such as the namespace
entries or the state of a commit. The service binds every token to that
commit, and the response includes its
commitId. Concurrent writes do not change the pages. - Live lists read current state, such as branches, tags, and Project events. A concurrent change can omit an entry or show it twice across pages. For a consistent view of a whole Project, read an immutable commit instead.
Page tokens on other services
Organizations, Projects, Storage, and workload identities use snake_case fields:
| Field | Direction | Meaning |
|---|---|---|
page_size | Query | The maximum number of entries. |
page_token | Query | The continuation from the previous page. |
items | Response | The entries in this page. |
next_page_token | Response | The continuation for the next page, or null. |
Watch out for one difference: some of these lists return every entry in one
page, and reject page_size and page_token with status 400. These lists are the Organizations of the caller
(GET /v1/organizations), Projects (GET /v1/projects), mounts, workloads, and
workload trust policies. Send no paging parameters to them.
The users and invitations of an Organization accept a page_size from 1 to 100,
and use 10 when you omit it.
Cursors on Tasks and worker pools
Tasks, worker pools, worker sessions, and task triggers use an item cursor:
| Field | Direction | Meaning |
|---|---|---|
limit | Query | The maximum number of entries, where the operation accepts it. |
after | Query | The ID of the last entry that you received. |
next | Response | The cursor for the next page. Absent or null on the last page. |
Send the value of next as after in the next request. The entries are in a
field named for them, such as tasks or workerSessions. Trigger lists use
items.
curl "https://api.spiraldb.dev/projects/$PROJECT_ID/tasks?after=$NEXT&limit=50" \
-H "Authorization: Bearer $SPIRAL_TOKEN"These cursors read live state. A cursor is an item ID, so a new entry that sorts before the cursor does not appear on later pages.