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 withoutcursor, 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,
sortandorderon every page. OnGET /v1/messages, writesinceanduntilthe same way on every page:2026-10-08T00:00:00Zand2026-10-08T00:00:00.000Zcount 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. OnGET /v1/lines/{id}/queue, and onGET /v1/messageswithsort=scheduled_for, an item can come back on a later page when iSnap holds its message again with a laterscheduled_for. OnGET /v1/messagessorted bycreated_at, and onGET /v1/pre-orders, the order never changes: an item you have already seen means that the list restarted. OnGET /v1/webhooks/events, the id of an item is itsevent_id. - Expect chats to move.
GET /v1/chatsorders 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/eventscovers the last 72 hours. A cursor that points past that window returns an empty page withhas_more: false, not an error. See Events feed.
GET /v1/messages also counts against the message-operations limit, which it shares with POST /v1/messages.
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.
Filters
A filter is a query parameter. Its name is insnake_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,sinceanduntilbound the time iSnap recorded the message. For a message that the line’s device reported late, that time is later thandelivered_at. - On
GET /v1/webhooks/events,sinceis required anduntildefaults to the time of the request. Asinceolder than 72 hours is raised to 72 hours ago, without an error. Asincelater thanuntilreturns an empty page.