schemas/pagination
All list operations return the same envelope:
{
"items": ["... resource objects ..."],
"pagination": {
"currentPage": "integer — 1-indexed",
"pageSize": "integer — items in this page",
"totalItems": "integer — total items matching the query; identical in both offset and cursor paging",
"nextCursor": "integer or date-time — cursor for the next page (type follows the resource key; messages use date-time)"
}
}
Page size
limit accepts integers 1–30 on every paginated operation. Omit it and a default page size is
applied — 10 on most operations, 30 on the ones whose items are small — and a wrapper_note names
the value applied. An integer above 30 is never rejected — the page is served at 30 with a
wrapper_note saying so; any other value fails validation.
Both spellings work everywhere: flat page / limit / startingAfter and the dotted
pageQuery.page / pageQuery.limit / pageQuery.startingAfter. Whichever an operation's Arguments
table lists is the canonical one; the other is accepted as an alias, so a spelling carried over from
another operation will not be rejected.
Requests are rate-limited per API key, not per operation (call-contract), so page size is also a budget decision: one
limit: 30call costs a third of threelimit: 10calls. Ask for the largest page you will actually use, and narrow with filters rather than walking many small pages.
Large bodies in list responses
On the list reads that return an email body — message/get,
prospect/messages_by_id, campaign/get,
sequence/get_followups_by_id — each item's body is bounded,
so a wide page cannot blow past your context or response limit:
- 1,500 characters or fewer: returned exactly as stored — unchanged HTML.
- Longer: a plain-text rendering of that HTML, cut at 1,500 characters on a word boundary and ending in a bracketed note giving the original length. The note describes the preview; it is not part of the message.
fullBodies: trueturns previewing off for that call — every body comes back complete and unchanged.*_by_idreads never preview: campaign/get_by_id, followup/get_by_id and the other single-object reads always return the full body.
Never write a previewed body back. Saving one into
bodywould replace a real email template with truncated plain text. Read the full body first — a*_by_idread, or the same list call withfullBodies: true— and edit that.
Paging styles
- Offset: pass
page+limit. Campaign operations prefix both arguments:pageQuery.page,pageQuery.limit. - Cursor: pass the previous response's
pagination.nextCursorasstartingAfter.
Cursor caveats
totalItemsis the collection total in both paging modes. It reflects the total number of matching items whether you're paging withpage/limitor withstartingAfter.
Empty sentinel:
nextCursor: "0001-01-01T00:00:00.000Z"means there are no more results.
Null and cursor semantics
pagination: nullon a 2xx response means single page — you already have everything. It staysnulleven though other null fields are stripped from responses.nextCursorcan be present even when the page already contains all items — never treat its presence alone as "more pages"; an empty next page is the true end signal.- The
sendingStatusfilter on prospect/get returns its own pagination object:{pageSize, returned, nextCursor?, exhausted}—exhausted: truemeans the account was fully scanned; anextCursor(last matched or last scanned prospect id) means "continue withstartingAfter", even when fewer thanpageSizeitems were returned.