Skip to content

Pagination & sync

Pagination & sync

Lists page through an opaque cursor. Syncing works with updatedSince and includeDeleted, next to webhooks too.

Paging

Ask for the next page with nextCursor as long as hasMore is true.
HTTP
GET /v1/contacts?limit=100&sort=-updatedAt

{
  "data": [ { "id": "con_4Nf7…", … }, … ],
  "hasMore": true,
  "nextCursor": "eyJ2IjoxLCJrIjoi…"
}

GET /v1/contacts?limit=100&sort=-updatedAt&cursor=eyJ2Ijox…

The SDKs walk the cursor themselves: for await (const contact of bodo.contacts.list()) or for contact in bodo.contacts.list().

Rules

ParameterRule
limitdefault 25, at most 100
cursorbound to filters and sort order, otherwise 400 CURSOR_MISMATCH; expires after 24 h
sortonly values from the reference, such as -updatedAt
unknown400 UNKNOWN_PARAMETER, there is no filter language
total countnot in lists, use GET /v1/contacts/count (2 points)

Syncing, next to webhooks too

Remember the start time of every run and ask only for changes next time. Deletion markers come with includeDeleted=true. Webhooks only report that something changed; you fetch the state exactly like this. If a resource has no deletion markers, its reference says so.
HTTP
GET /v1/contacts?updatedSince=2026-11-03T09:00:00Z&includeDeleted=true&limit=100

{"data": [
  {"id": "con_4Nf7…", "lastName": "Mustermann", "updatedAt": "2026-11-03T09:14:22Z"},
  {"id": "con_9Qa2…", "deleted": true, "updatedAt": "2026-11-03T10:02:51Z"}
], "hasMore": false, "nextCursor": null}
If your receiver is down for a while, catch up with updatedSince. You can also read events for 30 days through GET /v1/events.