Pagination
Almost every collection returns the same wrapper: data (the items) and pagination
(the navigation metadata). The exception is GET /v2/balances, which returns a bare
array: you hold one position per asset, so there is nothing to paginate. What changes is what pagination contains, because
v2 uses two strategies.
| Strategy | Where | Metadata |
|---|---|---|
| Offset (default) | Everything except fills | page, limit, totalItems, totalPages |
| Cursor | GET /v2/fills and GET /v2/orders/{id}/fills | count, nextCursor |
Offset — the general case
{
"data": [
{ "id": "wd_123", "status": "COMPLETED" },
{ "id": "wd_124", "status": "PENDING" }
],
"pagination": {
"page": 1,
"limit": 25,
"totalItems": 132,
"totalPages": 6
}
}
| Parameter | Description |
|---|---|
page | Page number. Starts at 1. Defaults to 1. |
limit | Items per page. Defaults to 25, maximum 100. |
Cursor — fills
The two fills endpoints paginate by cursor, not offset:
{
"data": [
{ "id": "1096473", "orderId": "clord_01H…", "baseAmount": "0.01" }
],
"pagination": {
"count": 25,
"nextCursor": "MjAyNi0wNy0yNiAxNzo0MjowMS4wMDMzMDl8OWY4Zi00YQ"
}
}
| Parameter | Description |
|---|---|
limit | Items per page. Defaults to 25, maximum 100. |
cursor | The previous page's pagination.nextCursor. Omit it on the first request. |
The correct walk: request a page, process data, and if nextCursor is not null,
request again passing it as cursor. Repeat until it is null.
count can be lower than the limit you asked for even when more results remain. The
only end-of-collection signal is nextCursor: null. A client that stops on a short page
silently misses data.
A fill is an execution record: append-only, never reordered. With OFFSET n the database
re-scans and discards n rows on every page and — what matters more in a money API — the
window shifts under you: a fill landing mid-walk pushes a row from page 2 onto page 3, and
a client paging through its own history silently skips it. A keyset cursor is stable
against concurrent inserts and costs the same on page 1 as on page 500.
It is also what the market does for this specific resource: Coinbase's /fills is
cursor-paged and Binance's myTrades walks by fromId. What you give up is the totals, and
for an append-only log "how many fills have I ever had" is not worth a full COUNT on every
page.
nextCursor is an opaque token: pass it back verbatim. Its encoding is not part of the
contract and may change. Do not parse it, do not construct one, and do not store it as if it
were a stable identifier.
Filters
In v2, filters are expressed as query parameters instead of special routes.
For example, to list the fills of an order use GET /v2/fills?orderId=… rather
than a dedicated route.
See the API Reference for the filters available on each collection.