Skip to main content
Eleven operations return a list. Six page with a cursor, one pages with a page number, and four return the whole list in one response. This page gives the rules of each, so that a walk of a list neither skips nor repeats an item.

List operations

limit is between 1 and 100. A value outside that range returns 400 validation_failed: it is not brought back into the range. A query parameter that the operation does not define is ignored, without an error: a misspelled filter returns the list unfiltered. Where the items are in data: The four operations without pages set no bound on the size of their response.

Cursors

To walk a cursor list, call it without cursor, then pass the next_cursor of each response as the cursor of the next request, with the same filters. Stop when has_more is false: next_cursor is then null. A cursor is an opaque string. It does not expire. It marks a position in the list, so that items with the same timestamp are neither repeated nor skipped. Use a cursor only with the operation that returned it. What a cursor is bound to differs by operation: Four rules follow:
  • Keep the query of a walk. Send the same filters, sort and order on every page. On GET /v1/messages, write since and until the same way on every page: 2026-10-08T00:00:00Z and 2026-10-08T00:00:00.000Z count as two values.
  • Deduplicate on id. On every cursor list, track the ids you have processed and skip an item you have already seen. Such an item means one of two things: the list restarted, or the place of the item in the order changed during the walk. On GET /v1/lines/{id}/queue, and on GET /v1/messages with sort=scheduled_for, an item can come back on a later page when iSnap holds its message again with a later scheduled_for. On GET /v1/messages sorted by created_at, and on GET /v1/pre-orders, the order never changes: an item you have already seen means that the list restarted. On GET /v1/webhooks/events, the id of an item is its event_id.
  • Expect chats to move. GET /v1/chats orders by latest activity. A chat that sends or receives a message during a walk moves to the front: the walk can miss it or return it twice. Deduplicate on the chat id, and walk again to catch the chats that moved.
  • Expect the events feed to end. GET /v1/webhooks/events covers the last 72 hours. A cursor that points past that window returns an empty page with has_more: false, not an error. See Events feed.
Each page is one request. It counts against the request-rate limit, and a page of GET /v1/messages also counts against the message-operations limit, which it shares with POST /v1/messages.
The samples import the helpers of Authentication. The SDK iterators do not expose the cursor: SDK pagination shows how to page by hand. The items of GET /v1/messages, GET /v1/chats and GET /v1/lines/{id}/queue carry personal data: handles and message text. Request them only when needed. Do not copy them into logs, tickets or other tools. Refer to a contact by an id of your own.

Page numbers

GET /v1/lines is the one list that pages by number. page starts at 1 and defaults to 1. Read total to know how many lines match the filters, and request pages until you have them all.
The marketplace changes between two requests: a line can leave the list and come back. Read the list again before you take a line. See Getting a line.

Filters

A filter is a query parameter. Its name is in snake_case. An invalid value returns 400 validation_failed, and error.issues names the parameter. The reference page of each operation lists the values every filter takes.

Timestamps in queries

since and until are inclusive bounds. Three rules:
  • URL-encode the value. A + in an offset must be sent as %2B.
  • On GET /v1/messages, since and until bound the time iSnap recorded the message. For a message that the line’s device reported late, that time is later than delivered_at.
  • On GET /v1/webhooks/events, since is required and until defaults to the time of the request. A since older than 72 hours is raised to 72 hours ago, without an error. A since later than until returns an empty page.
Timestamps in responses are ISO 8601 in UTC with milliseconds: see Timestamps.