# Pagination

The catalog list endpoints — `/v1/products`, `/v1/orders`, `/v1/customers`, `/v1/customers/{id}/orders` and `/v1/landing-pages` — use **cursor pagination**. Offsets are intentionally not supported.

Request:

```
GET /v1/products?limit=50&cursor=<opaque>
```

Response:

```
{ "data": {

    "items": [...],

    "next_cursor": "MTIz",

    "has_more": true

  } }
```

If `has_more` is `false`, you've drained the resource.

`limit` defaults to **50** and is clamped to 1–200: an out-of-range or non-numeric value is silently adjusted, not rejected. Pages walk newest-first, so the cursor points at the last item you received.

A malformed cursor is silently ignored

A truncated or corrupted `cursor` does not return `bad_request` — it is dropped and the list restarts from the newest record. Treat the token as fully opaque, pass it back byte-for-byte, and stop when `has_more` is `false`; a client that mangles the token will otherwise re-fetch page 1 forever.

## Endpoints that are not cursor-paginated

* `GET /v1/keys` and `GET /v1/webhooks` return the complete `items` array with no `next_cursor` / `has_more`.
* `GET /v1/usage/history` is range-based via `from` / `to` (90 days maximum) and returns `rows`.
