Pagination
Every list that grows without bound is paged with limit and an opaque cursor; how to walk one and why it never skips or repeats a row.
The shape
A paged list takes two query parameters and returns one extra field:
| Where | Name | Meaning |
|---|---|---|
| query | limit | rows per page; each route has a default and a maximum (the reference page for the route says which) |
| query | cursor | the next_cursor of the previous page; omit it for the first page |
| body | next_cursor | hand it back as cursor for the next page; empty on the last page |
Pages are newest first. The cursor is opaque — treat it as a string to hand back, never parse it — and one nobody issued is the first page rather than an error, so a stale bookmark degrades to a fresh start.
GET /v1/invoices?limit=50 HTTP/1.1
Authorization: Bearer aiml-live-…
HTTP/1.1 200 OK
{"data":[…50 invoices…],"next_cursor":"MjAyNi0wOS0xMlQxMDowMDowMFp8aW52XzAx"}
GET /v1/invoices?limit=50&cursor=MjAyNi0wOS0xMlQxMDowMDowMFp8aW52XzAx HTTP/1.1Why a cursor and not a page number
The cursor names where the previous page ended (the last row's time and id), and the next page is every row strictly older than that. A row written between two requests — a top-up that landed while you were reading page one — appears at the top of a fresh first page and never shifts the rows of page two, so walking a list to its end sees every row exactly once. An offset (page=2) cannot promise that.
Which lists page
| Route | Default / max limit | Filter |
|---|---|---|
GET /v1/keys | 100 / 200 | status (active, rotating, revoked, expired) |
GET /v1/requests | 50 / 500 | since, until, model, status |
GET /v1/credits/ledger | 50 / 500 | kind |
GET /v1/credits/topups | 50 / 200 | — |
GET /v1/credits/refunds | 50 / 200 | — |
GET /v1/invoices | 50 / 200 | — |
GET /v1/webhooks/{id}/deliveries | 50 / 200 | — |
GET /v1/org/scim/log | 100 / 500 | — |
Lists that are bounded by construction — models, projects, an org's webhooks, policies — are returned whole and carry no cursor.
In the SDKs
aiml.keys.list({ status: "active" }) and aiml.requests.list() in TypeScript, list_requests() in Python: each returns the page as the server sent it, with next_cursor beside data, and takes cursor and limit as parameters.