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

# Pagination

> Page through large result sets with cursor pagination, or keep using the legacy page/limit parameters.

## Overview

List endpoints support two pagination modes. Which one you get is decided by a
single parameter: **send `cursor` and you are in cursor mode, omit it and you
stay in legacy `page`/`limit` mode**.

Cursor pagination is the recommended mode for anything that walks a full result
set. It is stable under concurrent writes, and its cost does not grow as you
move deeper into the results.

<Info>
  Legacy `page`/`limit` pagination is still fully supported and unchanged. No
  existing integration needs to be updated.
</Info>

## Endpoints that support cursor pagination

| Endpoint                                                          | Legacy response key | Cursor mode notes                                                   |
| ----------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------- |
| [`GET /files`](/api-reference/endpoint/get-all-files)             | `files`             | —                                                                   |
| [`GET /schemas`](/api-reference/endpoint/get-all-schemas)         | `schemas`           | —                                                                   |
| [`GET /directories`](/api-reference/endpoint/get-all-directories) | `directories`       | `data` is a **flat** list of directories — no `subfolders` nesting. |

<Warning>
  `cursor`, `page`, `limit`, `sortBy`, and `sortOrder` come from one shared
  pagination parameter set, so `cursor` is also *listed* on
  [`GET /file-type`](/api-reference/endpoint/get-file-types),
  [`GET /schemas/file-type`](/api-reference/endpoint/get-file-type-schemas), and
  [`GET /files/{fileId}/values`](/api-reference/endpoint/get-file-schema-values-by-fileids).
  Those endpoints do not implement cursor mode yet: sending `cursor` there is
  accepted but ignored, and you still get the legacy `page`/`limit` response.
  Use `page`/`limit` on them.
</Warning>

## Cursor pagination

<Note>
  Examples use the default base URL, `https://api.orion.file.ai/prod/v1`. If
  your workspace is on an instance-specific host, swap the hostname and change
  nothing else — see [Switching between
  instances](/docs-api/api-intro#switching-between-instances).
</Note>

<Steps>
  <Step title="Request the first page">
    Send `cursor` with an **empty value** — the parameter's presence is what
    selects cursor mode.

    ```bash theme={null}
    curl -X GET "https://api.orion.file.ai/prod/v1/files?cursor=&limit=50" \
      -H "x-api-key: YOUR_API_KEY"
    ```
  </Step>

  <Step title="Read the pagination block">
    The response is wrapped in `data` plus a `pagination` object.

    ```json theme={null}
    {
      "data": [{ "id": "649e2d2d2d2d2d2d2d2d2d2d" }],
      "pagination": {
        "limit": 50,
        "nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI1LTA3LTMxVDA5OjE0OjIyLjEwMFoifQ==",
        "hasMore": true
      }
    }
    ```
  </Step>

  <Step title="Follow nextCursor until hasMore is false">
    Pass the previous `nextCursor` value back as `cursor`. When `hasMore` is
    `false`, `nextCursor` is `null` and you have reached the end.

    ```bash theme={null}
    curl -X GET "https://api.orion.file.ai/prod/v1/files?cursor=eyJjcmVhdGVkQXQiOiIyMDI1LTA3LTMxVDA5OjE0OjIyLjEwMFoifQ%3D%3D&limit=50" \
      -H "x-api-key: YOUR_API_KEY"
    ```

    <Warning>
      Cursor values are opaque and URL-encode them before use — they are
      base64 and can contain `=` characters.
    </Warning>
  </Step>
</Steps>

### Parameters

| Parameter | Type   | Required | Default     | Description                                                                    |
| --------- | ------ | -------- | ----------- | ------------------------------------------------------------------------------ |
| cursor    | string | No       | —           | Opaque cursor. Present (even empty) selects cursor mode; omitted keeps legacy. |
| limit     | number | No       | 50          | Page size in cursor mode. Maximum 100.                                         |
| sortBy    | string | No       | `createdAt` | In cursor mode, one of `createdAt`, `updatedAt`, `_id`.                        |
| sortOrder | string | No       | `ASC`       | `ASC` or `DESC`.                                                               |

### Pagination object

| Field      | Type           | Description                                                 |
| ---------- | -------------- | ----------------------------------------------------------- |
| limit      | number         | Page size actually applied (default 50, max 100).           |
| nextCursor | string \| null | Cursor for the next page; `null` when `hasMore` is `false`. |
| hasMore    | boolean        | Whether more results exist after this page.                 |

<Warning>
  A cursor is bound to the `sortBy`, `sortOrder`, and filter values it was
  minted with. Changing any of them mid-walk invalidates the cursor and returns
  a `422`. Start a new walk instead.
</Warning>

## Legacy page/limit pagination

Omit `cursor` entirely and the response keeps its original shape: a named array
(see the table above), plus `count` and `currentPage`.

```bash theme={null}
curl -X GET "https://api.orion.file.ai/prod/v1/files?page=1&limit=100" \
  -H "x-api-key: YOUR_API_KEY"
```

```json theme={null}
{
  "files": [{ "id": "649e2d2d2d2d2d2d2d2d2d2d" }],
  "count": 1350,
  "currentPage": 1
}
```

| Parameter | Type   | Required | Default     | Description                      |
| --------- | ------ | -------- | ----------- | -------------------------------- |
| page      | number | No       | 1           | Page number.                     |
| limit     | number | No       | 100         | Items per page.                  |
| sortBy    | string | No       | `createdAt` | Field to sort by.                |
| sortOrder | string | No       | `ASC`       | Sort direction (`ASC` or `DESC`) |

## Choosing a mode

<CardGroup cols={2}>
  <Card title="Use cursor pagination" icon="forward">
    Walking a full result set, syncing to a warehouse, or paging through data
    that is being written to concurrently.
  </Card>

  <Card title="Use page/limit" icon="table-list">
    You need a total `count`, jump-to-page behaviour, or you have an existing
    integration that already works.
  </Card>
</CardGroup>

<Note>
  Legacy mode gives you a total `count`; cursor mode does not — computing an
  exact total is what makes deep offset paging expensive. Use `hasMore` to drive
  your loop instead of a total.
</Note>
