# Pagination
Source: https://docs.file.ai/api/pagination

> Page through list endpoints with cursors, or with the legacy page and limit parameters.

Production

# Pagination

Copy pageCopy page

Page through list endpoints with cursors, or with the legacy page and limit parameters.

Copy pageCopy page

List endpoints return results a page at a time. Most support two modes, chosen by one parameter: **send `cursor` and you get cursor mode; leave it out and you get legacy `page`/`limit` mode**. Use cursor mode for anything that walks a whole result set — it stays correct while data changes and costs the same on page 500 as on page 1. Legacy mode is still fully supported. Existing integrations don’t need to change.

## 

[​

](#when-to-use-it)

When to use it

Use cursor mode when you…

Use legacy mode when you…

Walk a full result set or sync to a warehouse

Need a total `count`

Page through data that is being written to

Need to jump to a specific page

Want a stable order without extra parameters

Already have a working integration

Cursor mode has no total count — counting is what makes deep offset paging expensive. Drive your loop with `hasMore`.

## 

[​

](#how-it-works)

How it works

### 

[​

](#endpoints)

Endpoints

Endpoint

Cursor mode

Legacy mode

Legacy response key

`GET /v1/files`

Yes

Yes

`files`

`GET /v1/schemas`

Yes

Yes

`schemas`

`GET /v1/directories`

Yes — `data` is a **flat** list with no `subfolders` nesting

Yes

`directories`

`GET /v1/agent/sessions`

Only mode

No

—

`GET /v1/agent/sessions/{session_id}/messages`

Only mode

No

—

`cursor` is also listed on `GET /v1/file-type`, `GET /v1/schemas/file-type` and `GET /v1/files/{fileId}/values`, because they share the same parameter set. Those endpoints don’t implement cursor mode: `cursor` is accepted and ignored, and you get a legacy response. Use `page` and `limit` there.

### 

[​

](#cursor-mode)

Cursor mode

1

Request the first page

Send `cursor` with an empty value. Its presence is what switches on cursor mode. (`FILEAI_BASE_URL` is `https://api.orion.file.ai/prod/v1`, or your [regional host](/authentication#regions).)

```
curl "$FILEAI_BASE_URL/files?cursor=&limit=50" \
  -H "x-api-key: $FILEAI_API_KEY"
```

On the agent session and message lists, which only have cursor mode, you can simply omit `cursor` for the first page.

2

Read the pagination object

Results come back in `data`, with a `pagination` object:

```
{
  "data": [{ "fileId": "b765bd00-181e-4737-b4d9-004dadd6bd45" }],
  "pagination": {
    "limit": 50,
    "nextCursor": "<nextCursor>",
    "hasMore": true
  }
}
```

3

Follow nextCursor until hasMore is false

Pass `nextCursor` back as `cursor`, with the same filters and sort. When `hasMore` is `false`, `nextCursor` is `null` and you’re done.

```
curl "$FILEAI_BASE_URL/files?cursor=<nextCursor>&limit=50" \
  -H "x-api-key: $FILEAI_API_KEY"
```

Cursors are opaque, signed strings in unpadded base64url, so they are already safe to put in a URL. Don’t build, decode or edit them. A cursor only works with the request that produced it. It is bound to:

*   the endpoint and your workspace,
*   `sortBy` and `sortOrder`,
*   every filter on the request (for example `updatedAfter`, `directoryId`, `fileIds`).

Change any of these mid-walk, or send a cursor that has been altered, and you get `400 BAD_REQUEST` (“Please restart pagination”). Start a new walk without a cursor.

Sorting by `updatedAt` is best-effort: a row updated during your walk can move past the point you’ve reached and appear again, or be skipped until your next walk. `createdAt` and `_id` give an exact walk.

### 

[​

](#legacy-mode)

Legacy mode

Leave `cursor` out and the response keeps its original shape: a named array, plus `count` and `currentPage`.

```
curl "$FILEAI_BASE_URL/files?page=1&limit=100&sortBy=createdAt&sortOrder=ASC" \
  -H "x-api-key: $FILEAI_API_KEY"
```

```
{
  "files": [{ "fileId": "b765bd00-181e-4737-b4d9-004dadd6bd45" }],
  "count": 1350,
  "currentPage": 1
}
```

In legacy mode on `GET /v1/files` and `GET /v1/schemas`, results are only sorted when you send **both** `sortBy` and `sortOrder`. If either is missing, the order is unspecified and pages can overlap or skip rows. Always send both.

## 

[​

](#reference)

Reference

### 

[​

](#cursor-mode-parameters)

Cursor mode parameters

Parameter

Default

Description

`cursor`

—

Empty for the first page, then the previous `nextCursor`. Presence selects cursor mode.

`limit`

50

Page size. A value above 100 is reduced to 100. Zero, negative or repeated values are a `400`.

`sortBy`

`createdAt`

`createdAt`, `updatedAt` or `_id`. Anything else is a `400`.

`sortOrder`

`ASC`

`ASC` or `DESC`.

The agent lists take only `cursor` and `limit`, with their own order and sizes:

Endpoint

Order

Default `limit`

Maximum

`GET /v1/agent/sessions`

Newest first

50

100

`GET /v1/agent/sessions/{session_id}/messages`

Oldest first

20

50

### 

[​

](#pagination-object)

Pagination object

Field

Type

Description

`limit`

number

Page size actually applied.

`nextCursor`

string | null

Cursor for the next page; `null` when `hasMore` is `false`.

`hasMore`

boolean

Whether more results exist after this page.

### 

[​

](#legacy-mode-parameters)

Legacy mode parameters

Parameter

Default

Description

`page`

1

Page number.

`limit`

100

Items per page. There is no maximum; a zero, negative or non-numeric value falls back to 100.

`sortBy`

—

Field to sort by. Only applied together with `sortOrder`.

`sortOrder`

—

`ASC` or `DESC`. Only applied together with `sortBy`.

## 

[​

](#related)

Related

## Incremental loading

Combine cursors with `updatedAfter` to sync changes.

## Agent sessions

Cursor-only lists of sessions and messages.

## Errors

What a `400` for a bad cursor looks like.

## Authentication and regions

Base URLs and request conventions.

[Previous](/api/rate-limits)[

Retries

Send an Idempotency-Key so a retried write is never applied twice.

Next

](/api/idempotency)

⌘I

## On this page

*   [When to use it](#when-to-use-it)
*   [How it works](#how-it-works)
    *   [Endpoints](#endpoints)
    *   [Cursor mode](#cursor-mode)
    *   [Legacy mode](#legacy-mode)
*   [Reference](#reference)
    *   [Cursor mode parameters](#cursor-mode-parameters)
    *   [Pagination object](#pagination-object)
    *   [Legacy mode parameters](#legacy-mode-parameters)
*   [Related](#related)
