Pagination
Page through contacts and conversations with opaque cursors; which endpoints paginate and their page-size limits.
List endpoints that can grow without bound use cursor pagination: you ask for a page, and the response tells you where the next one starts. Cursors are stable — new rows arriving while you page don't make you skip or repeat items, unlike offset pagination.
#How it works
- Call the list endpoint with an optional
limit. - The response includes
nextCursor. - Pass it back as
cursoron the next request. - Stop when
nextCursorisnull. (When the last page happens to be exactly full, you get one more request that returns an empty list andnextCursor: null.)
curl "https://api.ody.co/v1/api/contacts?limit=100" \
-H "Authorization: Bearer $ODY_API_KEY"
# next page
curl "https://api.ody.co/v1/api/contacts?limit=100&cursor=eyJjIjoiMjAyNi0x…" \
-H "Authorization: Bearer $ODY_API_KEY"// The SDK follows nextCursor for you.
for await (const contact of ody.contacts.listAll({ limit: 200 })) {
console.log(contact.id);
}# The SDK follows nextCursor for you.
for contact in client.contacts.list_all(limit=200):
print(contact["id"])Response
{
"contacts": [{ "id": "8b1d…", "firstName": "Ada" }],
"nextCursor": "eyJjIjoiMjAyNi0xMC0xNFQxODowMjoxMS4wMDBaIiwiaSI6IjhiMWQ…"
}limitinteger — Page size. Defaults and maximums per endpoint below.cursorstring — The previous response'snextCursor, passed back verbatim. A modified or stale cursor returns400 invalid_argument.
#Limits per endpoint
| Endpoint | Paginates | Default limit | Max limit | Order |
|---|---|---|---|---|
GET /contacts | cursor | 50 | 200 | Newest created first |
GET /conversations | cursor | 50 | 100 | Most recent activity first |
GET /calls | limit only | 50 | 200 | Newest first |
GET /messages/search | limit only | 25 | 100 | Best match |
GET /numbers/available | limit only | 20 | 50 | Carrier order |
GET /webhooks/:id/deliveries | limit only | 50 | 200 | Newest first |
Syncing a large workspace
Use the maximum limit, and switch to webhooks (contact.updated, message.received) for incremental changes once the initial backfill is done — it's faster and stays well under the rate limit.
Last updated Wed Oct 14 2026 00:00:00 GMT+0000 (Coordinated Universal Time)Something wrong on this page? Tell us