Pagination and filters
GET /v1/messages returns 100 messages a page, newest first, and a next_cursor. Pass it as cursor to get the next page; it is null on the last page.
json
{
"data": [{ "id": "msg_CgdWeHQN4sPaZnXfh7kP5", "status": "delivered", "…": "…" }],
"next_cursor": "msg_CgdWeHQNnp4VN7KkfNqju"
}The cursor marks a position, not a page number: messages accepted while you page do not shift or repeat the following pages. Treat it as an opaque string.
Filters
| Parameter | |
|---|---|
status | One status, e.g. failed. |
channel | whatsapp or sms. |
to | A number in E.164; the + may be left out. |
reference | Your reference, exactly. |
template | A template name (of the channel, if given). |
from, until | Moments of acceptance, ISO 8601; until is exclusive. Without an offset the time is UTC. |
Filters combine with cursor: keep them the same on every page.
Example: reconcile a day
js
let cursor = null
do {
const params = new URLSearchParams({
from: '2026-11-01T00:00:00Z',
until: '2026-11-02T00:00:00Z',
})
if (cursor) params.set('cursor', cursor)
const response = await fetch(`https://api.ace-send.com/v1/messages?${params}`, {
headers: { Authorization: `Bearer ${process.env.ACE_SEND_API_KEY}` },
})
const page = await response.json()
for (const message of page.data) await save(message)
cursor = page.next_cursor
} while (cursor)Keep under the read limit of 20 requests a second per key.