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_..." }}Loop on has_more, never on data.length
Section titled “Loop on has_more, never on data.length”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.
// Correctlet 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 windowlet page = await fetchPage();while (page.data.length > 0) { /* … */ }The cursor binds your filters
Section titled “The cursor binds your filters”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.
What ordering by id guarantees
Section titled “What ordering by id guarantees”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:
curl ".../v1/meetings?meeting_after=2026-01-01T00:00:00Z&meeting_before=2026-02-01T00:00:00Z"Filters
Section titled “Filters”| Parameter | Filters on |
|---|---|
meeting_after / meeting_before | When the meeting or call happened. The filter most integrations want. |
created_after / created_before | When the record was created in Salesbud. |
owner_email | Exact, case-insensitive owner match. |
type | video or audio — the media, not the resource kind. |
audience | internal or external. |
has_transcript | Whether 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.