Pagination
List endpoints are cursor-paginated. They accept these query parameters:
| Field | Type | Description |
|---|---|---|
| cursor | string | An opaque cursor from a prior response’s nextCursor. Omit for the first page. |
| limit | integer | Page size, 1–200. Defaults to 50 when omitted. |
| q | string | An optional free-text search filter (where the endpoint supports it). |
The page envelope
Every list response is the same shape:
{
"data": [{ "id": "…" }],
"nextCursor": "eyJpZCI6IjAxOTAuLi4ifQ",
"hasMore": true
}data— the items on this page.nextCursor— the cursor to fetch the next page, ornullon the last page.hasMore—truewhile another page exists (it istrueexactly whennextCursoris non-null).
Following the cursor
Loop until hasMore is false:
async function listAll(path, headers) {
const items = [];
let cursor = null;
do {
const url = new URL(path, 'https://your-app.example.com');
if (cursor) url.searchParams.set('cursor', cursor);
url.searchParams.set('limit', '200');
const res = await fetch(url, { headers });
const page = await res.json();
items.push(...page.data);
cursor = page.nextCursor;
} while (cursor);
return items;
}Cursors are opaque
Treat nextCursor as a black box — pass it back verbatim. Do not parse, construct, or persist it as a
durable identifier; it encodes keyset position and may change shape over time.