> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spirii.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> How list endpoints return results in pages, and how to retrieve every result reliably.

List endpoints return results in pages rather than all at once. Cursor-based pagination is the standard across the Spirii API; some existing endpoints use offset-based pagination instead. An endpoint's reference page lists the exact parameters it accepts, so that is always the source of truth for how a given endpoint pages.

## Cursor pagination

The standard. You request a page, and the response hands you a cursor pointing at the next one. You keep following cursors until there are none left.

**Request parameters**

| Parameter            | Description                                                        | Default |
| -------------------- | ------------------------------------------------------------------ | ------- |
| `limit`              | Number of records to return, from 1 to 100                         | `25`    |
| `nextPageCursor`     | Cursor returned by a previous response, to fetch the next page     | —       |
| `previousPageCursor` | Cursor returned by a previous response, to fetch the previous page | —       |

**Response shape**

```json theme={null}
{
  "data": [ /* the records for this page */ ],
  "nextPageCursor": "My0xMDAw",
  "previousPageCursor": null
}
```

The cursors are opaque strings — don't parse or build them, only pass back what you received. When there are no further results, `nextPageCursor` comes back empty.

### Page through every result

Request the first page, then keep passing the returned `nextPageCursor` back until it's empty:

```bash theme={null}
# First page
curl https://api.spirii.com/v2/chargeboxes?limit=100 \
  -H "Authorization: Bearer <SPIRII_API_KEY>"

# Next page — pass the nextPageCursor from the previous response
curl "https://api.spirii.com/v2/chargeboxes?limit=100&nextPageCursor=My0xMDAw" \
  -H "Authorization: Bearer <SPIRII_API_KEY>"
```

In code, loop until the cursor runs out:

```javascript theme={null}
async function fetchAll() {
  const results = [];
  let cursor;

  do {
    const url = new URL("https://api.spirii.com/v2/chargeboxes");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("nextPageCursor", cursor);

    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${SPIRII_API_KEY}` },
    });
    const body = await res.json();

    results.push(...body.data);
    cursor = body.nextPageCursor;
  } while (cursor);

  return results;
}
```

Cursor responses don't include a total count, so you can't show "page 3 of 20" or jump to an arbitrary page. You page forward (or back) until the cursor is empty. This keeps paging stable even while records are being added or removed underneath you.

## Offset pagination

Some existing endpoints page by offset instead: you ask for a `limit` and skip a number of records with `offset`.

| Parameter | Description                                                | Default            |
| --------- | ---------------------------------------------------------- | ------------------ |
| `limit`   | Number of records to return                                | Varies by endpoint |
| `offset`  | Number of records to skip from the start of the result set | `0`                |

Offset responses include a `count` — the total number of records matching your query — so you can calculate how many pages there are. To walk the full set, increase `offset` by `limit` on each request until `offset` reaches `count`:

```bash theme={null}
# First page
curl "https://api.spirii.com/v2/tokens?limit=500&offset=0" \
  -H "Authorization: Bearer <SPIRII_API_KEY>"

# Second page
curl "https://api.spirii.com/v2/tokens?limit=500&offset=500" \
  -H "Authorization: Bearer <SPIRII_API_KEY>"
```

## Which pagination an endpoint uses

Check the endpoint's parameters in the [API reference](/api-reference/overview): a `nextPageCursor` parameter means cursor-based, an `offset` parameter means offset-based. Two differences catch people out when moving between endpoints:

* **Default and maximum page size vary.** A cursor endpoint might default to 25 records (max 100), while an offset endpoint defaults to 500 (max 1000). Set `limit` explicitly rather than relying on the default.
* **Only offset responses return a total.** If you need a count, read it from `count` on an offset endpoint; cursor endpoints don't provide one.

<Info>
  If your integration reads from several endpoints, handle both styles: branch on whether the response returns a `nextPageCursor` or a `count`, rather than assuming one scheme everywhere.
</Info>

## Related

<CardGroup cols={2}>
  <Card title="Filtering" icon="filter" href="/developers/filtering">
    Narrow and sort list results with query parameters.
  </Card>

  <Card title="API reference" icon="square-terminal" href="/api-reference/overview">
    The exact pagination parameters each endpoint accepts.
  </Card>
</CardGroup>
