---
title: "Paginación — API v3 de AllSign"
type: explanation
canonical_url: "https://allsign.io/developers/docs/pagination"
api_version: "2026-07-11"
---

# Paginación

Todos los endpoints de lista de la API v3 usan **paginación por cursor**. Los cursores son **opacos**: son cadenas que solo AllSign entiende. No los construyas, no los decodifiques y no infieras nada de su contenido — solo pásalos de vuelta tal cual. Un cursor malformado o adivinado devuelve `400 INVALID_CURSOR`.

## El sobre de lista

Toda lista responde con el mismo **sobre (envelope)**: `object: "list"`, el arreglo `data`, y los metadatos de paginación. Nunca recibes un arreglo pelón.

```
{
  "object": "list",
  "data": [ /* ... los recursos de esta página ... */ ],
  "hasMore": true,
  "nextCursor": "djF8Y3JlYXRlZEF0fC4uLg",
  "previousCursor": null,
  "limit": 20,
  "totalCount": null
}
```

| Campo | Qué es |
| --- | --- |
| `object` | Siempre `"list"`. |
| `data` | Los recursos de esta página, en orden. |
| `hasMore` | `true` si hay más páginas después de esta. **Tu señal de fin de loop.** |
| `nextCursor` | Cursor opaco para la página siguiente (o `null` si no hay). |
| `previousCursor` | Cursor opaco para la página anterior (o `null`). |
| `limit` | El tamaño de página efectivo que se aplicó. |
| `totalCount` | El total de la colección — `null` salvo que pidas `includeTotal=true`. |

## Parámetros

| Parámetro | Qué hace |
| --- | --- |
| `limit` | Recursos por página. Rango **1–100**, **default 20**. |
| `startingAfter` | Cursor: trae la página *después* de este punto (avanzar). |
| `endingBefore` | Cursor: trae la página *antes* de este punto (retroceder). |

`startingAfter` y `endingBefore` son **mutuamente excluyentes**: si mandas ambos, obtienes `422 VALIDATION_ERROR`. Elige una dirección por petición.

Al paginar, **mantén fijos el orden y los filtros** entre peticiones. Un cursor está atado al conjunto de `sort` + filtros con el que lo generaste; cambiarlos a media paginación produce resultados inconsistentes. Y recuerda: si el cursor no es válido para esa consulta, la API responde `400 INVALID_CURSOR`.

## Recorrer todas las páginas

El patrón correcto es un bucle `while` guiado por `hasMore`: mientras sea `true`, pasa el `nextCursor` de la respuesta como `startingAfter` de la siguiente petición. **No** uses `totalCount` para decidir cuándo parar.

JavaScript:

```
async function listAll() {
  const out = [];
  let cursor = null;
  let hasMore = true;

  while (hasMore) {
    const url = new URL("https://api.allsign.io/v3/documents");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("startingAfter", cursor);

    const res = await fetch(url, {
      headers: { Authorization: "Bearer " + process.env.ALLSIGN_API_KEY, "AllSign-Version": "2026-07-11" },
    });
    const page = await res.json();

    out.push(...page.data);
    hasMore = page.hasMore;
    cursor = page.nextCursor;
  }
  return out;
}
```

Python:

```
import os, requests

def list_all():
    out, cursor = [], None
    while True:
        params = {"limit": 100}
        if cursor:
            params["startingAfter"] = cursor
        r = requests.get(
            "https://api.allsign.io/v3/documents",
            headers={"Authorization": f"Bearer {os.environ['ALLSIGN_API_KEY']}", "AllSign-Version": "2026-07-11"},
            params=params,
        )
        page = r.json()
        out.extend(page["data"])
        if not page["hasMore"]:
            break
        cursor = page["nextCursor"]
    return out
```

cURL (una página; encadena manualmente con el `nextCursor` devuelto):

```
# Primera página
curl "https://api.allsign.io/v3/documents?limit=100" \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"

# Siguiente página: pega el nextCursor de la respuesta anterior
curl "https://api.allsign.io/v3/documents?limit=100&startingAfter=djF8Y3JlYXRlZEF0fC4uLg" \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

Regla de oro: el loop termina cuando `hasMore === false`, no cuando llegas a un total. Así funciona aunque la colección crezca mientras paginas.

## Conteo total

`totalCount` es `null` por default. Solo se calcula si pides `includeTotal=true`, y ese cálculo es **caro** (escanea la colección completa). Pídelo únicamente cuando de verdad necesites mostrar un total (p.ej. "1 284 documentos" en una UI), y **nunca** lo uses como condición para terminar tu loop de paginación — para eso está `hasMore`.

```
curl "https://api.allsign.io/v3/documents?limit=20&includeTotal=true" \
  -H "Authorization: Bearer $ALLSIGN_API_KEY" \
  -H "AllSign-Version: 2026-07-11"
```

```
{
  "object": "list",
  "data": [ /* ... */ ],
  "hasMore": true,
  "nextCursor": "djF8Y3JlYXRlZEF0fC4uLg",
  "limit": 20,
  "totalCount": 1284
}
```
