Skip to content

Pagination

Lists are paginated with signed keyset cursors ordered by ascending id. The default page size is 50 and the maximum is 100.

{
"data": [ /* … */ ],
"pagination": { "limit": 50, "has_more": true, "next_cursor": "cur_..." }
}

This is the single most common integration bug against this API.

A page can come back short, or even empty, while has_more is true. The service caps how much it scans per request, so when a window is sparse the remaining rows are served on the next call rather than in a slower single response.

// Correct
let cursor = null;
do {
const page = await fetchPage(cursor);
await handle(page.data);
cursor = page.pagination.next_cursor;
} while (cursor);
// Wrong — stops early on a sparse window
let page = await fetchPage();
while (page.data.length > 0) { /* … */ }

next_cursor is signed and covers every filter of the request that produced it. Send it back unchanged, with identical filters. Changing a filter mid-walk, or editing the cursor, returns 400 INVALID_CURSOR instead of silently returning a different slice.

To change filters, start a new traversal from no cursor.

Ordering by ascending id makes a traversal stable without a snapshot: records created while you paginate get higher ids, so they land after your current position and never shift a page you already read.

The trade-off is the mirror image: a record that becomes completed after you have already passed its id is not picked up by the traversal in progress. It appears on your next pass over that window.

This is why v1 has no incremental sync — there is no dedicated “became visible” timestamp to make a delta honest. updated_at is informative only; do not use it as a sync watermark. Re-query by period instead:

Terminal window
curl ".../v1/meetings?meeting_after=2026-01-01T00:00:00Z&meeting_before=2026-02-01T00:00:00Z"
ParameterFilters on
meeting_after / meeting_beforeWhen the meeting or call happened. The filter most integrations want.
created_after / created_beforeWhen the record was created in Salesbud.
owner_emailExact, case-insensitive owner match.
typevideo or audio — the media, not the resource kind.
audienceinternal or external.
has_transcriptWhether a transcript resource exists.

All timestamps are RFC 3339 with an explicit offset. 2026-01-01T00:00:00Z is valid; 2026-01-01 is not, and returns 400 INVALID_DATETIME.