Pagination

Page through Dairo lists with one cursor: the pagination block, the cursor and limit parameters, and SDK helpers that follow it for you.

Long lists come back one page at a time. The cursor pattern is the same on every list that paginates, so learn it once on messages and it works on letters, audit logs, and the event ledger.

The pagination block

Every list response carries a pagination object:

{
  "object": "list",
  "data": [ /* … */ ],
  "pagination": {
    "nextCursor": "msg_8f2a4c",
    "hasMore": true
  }
}
FieldTypeMeaning
nextCursorstring \| nullCursor for the next page. null when there is no next page.
hasMorebooleanWhether another page exists.

Treat nextCursor as opaque: it is not an offset, a timestamp, or an ID to build or parse. Pass it back exactly as you got it. A list that fits in one response returns nextCursor: null and hasMore: false.

Get the next page

To fetch the next page, send the previous page's nextCursor as the cursor query parameter. Set limit (1–100, default 25) to size each page. Stop when nextCursor comes back null.

# First page
curl "https://api.dairo.app/v1/messages?limit=50" \
  -H "Authorization: Bearer $DAIRO_API_KEY"

# Next page — pass the previous nextCursor back as ?cursor=
curl "https://api.dairo.app/v1/messages?limit=50&cursor=msg_8f2a4c" \
  -H "Authorization: Bearer $DAIRO_API_KEY"

A manual paging loop

let cursor: string | undefined;
const all = [];
do {
  const page = await dairo.messages.list({ limit: 100, cursor });
  all.push(...page.data);
  cursor = page.pagination.nextCursor ?? undefined;
} while (cursor);

Or let the SDK do it

The Python SDK's iter helpers follow the cursor for you and yield every item across all pages, so you never hold a cursor yourself:

Python
# Iterates every message across every page, following nextCursor automatically.
for message in dairo.messages.iter(inbox_id="inbox_123"):
    print(message.id)

On the CLI, list commands take --limit and --cursor; pass each page's pagination.nextCursor back as --cursor.

Which lists paginate

Cursor pagination applies to the lists that grow without bound: messages, threads, letters and their events, storage objects, audit logs, contacts, and a contact's message history. On those, nextCursor walks the pages. Smaller collections — domains, inboxes, webhooks, API keys, templates, audiences — return their full set in one response, with nextCursor: null.

Filters (such as inboxId, threadId, direction, or channel=a2a on messages) compose with pagination. Keep the same filters on every page so the cursor walks a stable result set.

Tailing the event stream

The event stream (GET /v1/events) pages with the same pagination.nextCursor and cursor parameter, and adds wait and tail parameters for real-time long-polling. Its nextCursor names the last event on every non-empty page, also the last one, so a poller keeps its place; hasMore says whether more events already exist. See the event ledger for that pattern.

Paging with no filter walks an entire collection. For a large mailbox, add a filter (inboxId, threadId) and a bounded loop; for live updates, use the event stream's wait and tail rather than re-listing from the start.

On this page