Skip to main content

Cursor-Based Pagination

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
    }
  }
}
FieldTypeDescription
cursorstringOpaque cursor pointing to the last item in the current page
has_morebooleanWhether more results exist beyond this page
totalintegerTotal number of matching items (when available)

Quick Start

First Page

Request without a cursor to get the first page:
curl "https://api.orbit.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://api.orbit.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:
ParameterTypeDefaultDescription
cursorstringCursor from a previous response to fetch the next page
limitinteger25Number of items per page (1–200)

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`)

Python / Go / Other languages

First-party SDKs for Python, Go, Java, Ruby, PHP, and .NET are built and in beta but not yet published to their package registries. Until then, hit the REST endpoint directly (requests, httpx, net/http, OkHttp, etc.) — the cursor pattern above maps 1:1 onto any HTTP client.

Best Practices

  1. Use a reasonable page size. limit=200 is the maximum. For most use cases, 20–50 is sufficient.
  2. Do not store cursors long-term. Cursors are opaque and may expire. They are meant for sequential iteration, not bookmarking.
  3. Do not modify cursors. Cursors are server-generated tokens. Altering them will return a 400 Bad Request.
  4. Handle empty pages. If a page returns an empty data array with has_more: false, iteration is complete.
  5. Combine with filters. Apply query filters alongside pagination to narrow results before iterating:
curl "https://api.orbit.devotel.io/api/v1/messages?channel=sms&status=delivered&limit=50" \
  -H "X-API-Key: dv_live_sk_your_key_here"

Why Cursor-Based Pagination?

FeatureCursor-BasedOffset-Based
Consistency during concurrent writesStableMay skip or duplicate items
Performance on large datasetsO(1) per pageDegrades with high offsets
Supported by OrbitYesNo
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.