Concepts

Pagination

Lists return a page of results and an opaque cursor for the next one. Follow next_cursor until it's null.

Lists

GET/v1/trades, GET/v1/transactions and GET/v1/giftcards return the newest entries first, one page at a time:

A page
{
  "data": [{ "id": "tr_01JB8X2Q4M7Z3V9K5T1N6R0P2W", "…": "…" }],
  "next_cursor": "eyJpZCI6IjY3MjdhMWMzIn0"
}
ParameterMeaning
limitPage size, 1 to 100. The default is 50.
cursorThe next_cursor of the previous page. Leave it out for the first page.
fromOnly entries at or after this time (ISO 8601, Z or an offset).
toOnly entries at or before this time. At most 366 days after from.

Each list also has its own filters, such as asset, side, type or status; see the reference. Unknown parameters are rejected with 400 invalid_request.

Following the cursor

  • next_cursor is null on the last page.
  • The cursor is opaque. Don't build or change one; pass it back as it is.
  • Keep the same filters on every page of one listing.

The SDKs' listAll (list_all in Python) follows the cursor for you:

for await (const trade of client.trades.listAll({ asset: "BTC" })) {
  console.log(trade.created_at, trade.side, trade.base_amount);
}
for trade in client.trades.list_all(asset="BTC"):
    print(trade["created_at"], trade["side"], trade["base_amount"])

Or one page at a time:

let cursor: string | undefined;
do {
  const page = await client.transactions.list({ limit: 100, cursor });
  for (const entry of page.data) console.log(entry.id, entry.label);
  cursor = page.next_cursor ?? undefined;
} while (cursor);
cursor = None
while True:
    page = client.transactions.list(limit=100, cursor=cursor)
    for entry in page["data"]:
        print(entry["id"], entry["label"])
    cursor = page["next_cursor"]
    if cursor is None:
        break

Time ranges

from and to cover at most 366 days per request, and from must not be after to. For a longer history, ask year by year. In Python, from is a keyword, so the SDK takes it as from_: client.trades.list(from_="2026-01-01T00:00:00Z").