All Orbit list endpoints use cursor-based pagination for consistent, efficient navigation through large result sets. Unlike offset-based pagination, cursors ensure stable results even as data changes.
Overview
Every paginated response includes a pagination object in the meta field:
{
"data": [...],
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-03-08T12:00:00Z",
"pagination": {
"cursor": "cur_msg_abc123",
"has_more": true,
"total": 1542
}
}
}
| Field | Type | Description |
|---|
cursor | string | Opaque cursor pointing to the last item in the current page |
has_more | boolean | Whether more results exist beyond this page |
total | integer | Total number of matching items (when available) |
Quick Start
First Page
Request without a cursor to get the first page:
curl "https://orbit-api.devotel.io/api/v1/messages?limit=10" \
-H "X-API-Key: dv_live_sk_your_key_here"
Next Page
Pass the cursor from the previous response to get the next page:
curl "https://orbit-api.devotel.io/api/v1/messages?limit=10&cursor=cur_msg_abc123" \
-H "X-API-Key: dv_live_sk_your_key_here"
Continue Until Done
Keep paginating until has_more is false.
Parameters
All list endpoints accept these pagination parameters:
| Parameter | Type | Default | Description |
|---|
cursor | string | — | Cursor from a previous response to fetch the next page |
limit | integer | 20 | Number of items per page (1–100) |
Examples
Node.js — Iterate All Messages
const orbit = new Devotel({ apiKey: 'dv_live_sk_xxxx' })
let cursor = undefined
let allMessages = []
do {
const response = await orbit.messages.list({
limit: 100,
cursor,
channel: 'sms',
})
allMessages = allMessages.concat(response.data)
cursor = response.meta.pagination.has_more
? response.meta.pagination.cursor
: undefined
} while (cursor)
console.log(`Fetched ${allMessages.length} messages`)
orbit = OrbitClient(api_key="dv_live_sk_xxxx")
all_contacts = []
cursor = None
while True:
response = orbit.contacts.list(limit=100, cursor=cursor)
all_contacts.extend(response.data)
if not response.meta.pagination.has_more:
break
cursor = response.meta.pagination.cursor
print(f"Fetched {len(all_contacts)} contacts")
Go — Iterate All Agents
client := orbit.NewClient("dv_live_sk_xxxx")
var allAgents []orbit.Agent
cursor := ""
for {
resp, err := client.Agents.List(ctx, &orbit.ListParams{
Limit: 100,
Cursor: cursor,
})
if err != nil {
log.Fatal(err)
}
allAgents = append(allAgents, resp.Data...)
if !resp.Meta.Pagination.HasMore {
break
}
cursor = resp.Meta.Pagination.Cursor
}
fmt.Printf("Fetched %d agents\n", len(allAgents))
Best Practices
-
Use a reasonable page size.
limit=100 is the maximum. For most use cases, 20–50 is sufficient.
-
Do not store cursors long-term. Cursors are opaque and may expire. They are meant for sequential iteration, not bookmarking.
-
Do not modify cursors. Cursors are server-generated tokens. Altering them will return a
400 Bad Request.
-
Handle empty pages. If a page returns an empty
data array with has_more: false, iteration is complete.
-
Combine with filters. Apply query filters alongside pagination to narrow results before iterating:
curl "https://orbit-api.devotel.io/api/v1/messages?channel=sms&status=delivered&limit=50" \
-H "X-API-Key: dv_live_sk_your_key_here"
| Feature | Cursor-Based | Offset-Based |
|---|
| Consistency during concurrent writes | Stable | May skip or duplicate items |
| Performance on large datasets | O(1) per page | Degrades with high offsets |
| Supported by Orbit | Yes | No |
Orbit exclusively uses cursor-based pagination to guarantee consistent, performant results regardless of dataset size.
Offset-based pagination (?page=2 or ?offset=20) is not supported by any Orbit endpoint.