---
title: "Paginación"
description: "Cómo las operaciones de lista devuelven una página a la vez y cómo leer la página siguiente con un cursor."
---

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

# Paginación

Las operaciones de lista responden una página a la vez, en un orden estable. Cada página lleva cursores opacos que conducen a las páginas que la rodean.

## Pedir una página

| Parámetro | Por defecto | Significado |
| --- | --- | --- |
| `limit` | `25` | La cantidad máxima de elementos en una página, de 1 a 100. Para leer más se necesita otra página. |
| `cursor` | Ninguno | Un cursor del `pageInfo` de la respuesta anterior. Omítelo para la primera página. |
| `direction` | `forward` | En qué sentido recorrer el orden desde `cursor`: `forward` o `backward`. |

La mayoría de las listas son operaciones `GET` y los reciben como parámetros de query. Las búsquedas que se envían con `POST` los reciben en el cuerpo JSON, como [`agenda.appointments.search`](/api/agenda/appointments/search/) y [`raiz.knowledge.search`](/api/raiz/knowledge/search/).

Unas pocas operaciones fijan sus propios límites para `limit`. `agenda.appointments.list` admite hasta 500, y `raiz.knowledge.search` usa 8 por defecto con un máximo de 20. La referencia de la operación indica sus límites.

## Leer la página

El `data` de una lista es una página:

| Campo | Significado |
| --- | --- |
| `object` | Siempre `"list"`. |
| `data` | Los elementos de esta página. |
| `pageInfo.hasNextPage` | Si existe una página posterior en el orden actual. |
| `pageInfo.hasPreviousPage` | Si existe una página anterior en el orden actual. |
| `pageInfo.nextCursor` | El cursor de la página siguiente, o `null` si no hay. |
| `pageInfo.previousCursor` | El cursor de la página anterior, o `null` si no hay. |

Por ejemplo, la primera página de [`account.apiKeys.list`](/api/account/api-keys/list/), de una sola key. La llamada necesita el permiso (scope) `account:api-keys:read`:

```bash
curl "https://api.getarbol.com/v1/account/api-keys?limit=1" \
  --header "Authorization: Bearer $ARBOL_API_KEY"
```

```json
{
  "success": true,
  "data": {
    "object": "list",
    "data": [
      {
        "id": "exampleClientId0001",
        "name": "Billing backend",
        "scopes": ["account:billing:read"],
        "createdAt": "2026-10-01T15:00:00.000Z",
        "createdBy": null,
        "restrictions": null
      }
    ],
    "pageInfo": {
      "hasNextPage": true,
      "hasPreviousPage": false,
      "nextCursor": "EXAMPLE_CURSOR_2",
      "previousCursor": null
    }
  },
  "error": null,
  "metadata": { "requestId": "00000000-0000-4000-8000-000000000003" }
}
```

## Leer todas las páginas

Llama sin cursor y luego vuelve a llamar con `cursor` igual a `pageInfo.nextCursor` mientras `pageInfo.hasNextPage` sea `true`. Mantén iguales todos los demás parámetros.

### curl

```bash
cursor=""
while :; do
  params=(--data-urlencode "limit=100")
  if [ -n "$cursor" ]; then params+=(--data-urlencode "cursor=$cursor"); fi
  page=$(curl -sS --get https://api.getarbol.com/v1/account/api-keys "${params[@]}" \
    --header "Authorization: Bearer $ARBOL_API_KEY")
  jq -e '.success' <<<"$page" >/dev/null || { echo "$page" >&2; break; }
  jq -c '.data.data[]' <<<"$page"
  [ "$(jq -r '.data.pageInfo.hasNextPage' <<<"$page")" = "true" ] || break
  cursor=$(jq -r '.data.pageInfo.nextCursor' <<<"$page")
done
```

### TypeScript

```ts
import { createClient } from "@arbol-ai/sdk";

const arbol = createClient({
  baseUrl: "https://api.getarbol.com",
  token: process.env.ARBOL_API_KEY!,
});

let cursor: string | undefined;
do {
  const { data: page } = await arbol.account.apiKeys.list({ limit: 100, cursor });
  for (const key of page.data) console.log(key.id, key.name);
  cursor = page.pageInfo.hasNextPage ? (page.pageInfo.nextCursor ?? undefined) : undefined;
} while (cursor);
```

## Reglas de los cursores

- **Los cursores son opacos.** Úsalos exactamente como los devolvió la API. No construyas, edites ni decodifiques ninguno.
- **Un cursor pertenece a su consulta.** Envíalo con los mismos filtros que lo produjeron. Raíz rechaza un cursor de otra lista con `400 INVALID_CURSOR`.
- **Algunas lecturas no paginan.** Unas pocas reciben solo `limit` y no responden `pageInfo`, como [`agenda.firstAvailability.get`](/api/agenda/first-availability/get/). Su referencia lo indica.

Source: https://docs.getarbol.com/developers/concepts/pagination/index.mdx
