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

# Cursor-Based Pagination for Slate API List Endpoints

> Slate list endpoints use cursor-based pagination. Pass a cursor token from the previous response to retrieve the next page of results.

Every list endpoint in the Slate API returns results using cursor-based pagination. Instead of page numbers, Slate returns an opaque cursor string in each response that you pass back on your next request to fetch the following page. This approach is stable under concurrent writes — new accounts placed between your requests will not cause records to shift between pages.

## Query Parameters

All list endpoints accept the following pagination query parameters:

| Parameter        | Type    | Default  | Description                                                                                                                        |
| ---------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `limit`          | integer | `100`    | Number of records to return per page. Maximum is `500` on account list endpoints; check individual endpoint docs for other limits. |
| `cursor`         | string  | *(none)* | Opaque cursor from the previous response's `nextCursor` (or `previousCursor`) field. Omit on your first request.                   |
| `orderBy`        | string  | varies   | Field to sort results by. See individual endpoint docs for supported values.                                                       |
| `orderDirection` | string  | `asc`    | Sort direction. Accepts `asc` or `desc`.                                                                                           |

## Response Shape

A list response has two top-level parts: the page of records under a key named after the resource — never a generic `data` key — and a `pagination` object holding the cursor metadata. For example, the Accounts list endpoint returns records under `accounts`, and other endpoints use `creditors`, `firms`, `files`, `fileRequests`, `users`, `qcChecklists`, `qcRequests`, `redactions`, or `signatureRequests`.

```json theme={null}
{
  "accounts": [ /* array of records */ ],
  "pagination": {
    "totalCount": 4821,
    "nextCursor": "eyJpZCI6IjEyMyJ9",
    "previousCursor": ""
  }
}
```

* **The resource array** (`accounts` here) — The records for the current page, keyed by the resource name.
* **`pagination.totalCount`** — The total number of matching records across all pages. Use this to display progress or pre-allocate storage.
* **`pagination.nextCursor`** — The cursor to pass on your next request. When you are on the last page, `nextCursor` is an **empty string** (`""`). Stop paginating when you receive an empty cursor.
* **`pagination.previousCursor`** — The cursor for the previous page. It is an empty string (`""`) on the first page.

<Note>
  Every list endpoint across the Accounts, Files, Signatures, Quality Control, and Users APIs uses this same shape — records under a resource-named key and cursor metadata under `pagination`. The Files API also includes a `pagination.countExceedsLimit` boolean, which is `true` when the true total is larger than the reported `totalCount`.
</Note>

## Paginating Through All Results

Follow these steps to retrieve every record from a list endpoint.

<Steps>
  <Step title="Send your first request without a cursor">
    Make a `GET` request to the list endpoint with your desired `limit` and any filter parameters. Do not include a `cursor` parameter on this initial call.

    ```bash theme={null}
    curl --request GET \
      --url "https://api.slate.inc/accounts/v1/accounts?owner=<owner-id>&limit=100&orderBy=createdAt&orderDirection=asc" \
      --header "Authorization: Bearer <your-token>"
    ```

    Response:

    ```json theme={null}
    {
      "accounts": [ /* 100 accounts */ ],
      "pagination": {
        "totalCount": 4821,
        "nextCursor": "eyJpZCI6IjEwMCJ9",
        "previousCursor": ""
      }
    }
    ```
  </Step>

  <Step title="Check the nextCursor value">
    If `pagination.nextCursor` is a non-empty string, more records are available. If it is `""`, you have received the last page and should stop.
  </Step>

  <Step title="Pass the cursor on your next request">
    Add `cursor=<nextCursor>` to your query parameters, keeping all other parameters identical. Changing `limit`, `orderBy`, or filter values while paginating will produce unpredictable results.

    ```bash theme={null}
    curl --request GET \
      --url "https://api.slate.inc/accounts/v1/accounts?owner=<owner-id>&limit=100&orderBy=createdAt&orderDirection=asc&cursor=eyJpZCI6IjEwMCJ9" \
      --header "Authorization: Bearer <your-token>"
    ```

    Response:

    ```json theme={null}
    {
      "accounts": [ /* next 100 accounts */ ],
      "pagination": {
        "totalCount": 4821,
        "nextCursor": "eyJpZCI6IjIwMCJ9",
        "previousCursor": "eyJpZCI6IjAifQ"
      }
    }
    ```
  </Step>

  <Step title="Repeat until nextCursor is empty">
    Continue requesting pages, each time passing the `pagination.nextCursor` from the previous response, until you receive a response where `nextCursor` equals `""`. That response contains the final page of records.

    ```json theme={null}
    {
      "accounts": [ /* final batch of accounts */ ],
      "pagination": {
        "totalCount": 4821,
        "nextCursor": "",
        "previousCursor": "eyJpZCI6IjQ3MDAifQ"
      }
    }
    ```
  </Step>
</Steps>

## Cursor Opacity

Cursors are **opaque** — they are base64-encoded internal state that Slate uses to resume a query at the correct position. Do not attempt to parse, decode, or manually construct cursor values. The internal format may change without notice, and hand-crafted cursors will be rejected or return incorrect results.

<Warning>
  Always store and pass back cursor values exactly as returned in the response. Do not URL-encode or decode the cursor value yourself — your HTTP client will handle encoding when it appends the cursor to the query string.
</Warning>
