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

# Paginació

> Recorreu les llistes de la Living Security Public API amb l'envolupant de llista, el paràmetre limit i els cursors opacs page_token.

Cada endpoint de llista de `/v1` retorna el mateix envolupant i pagina de la
mateixa manera: basada en tokens i només cap endavant.

## L'envolupant de llista

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "ent_8f3d2c1b0a9e",
      "object": "entity",
      "type": "person",
      "status": "active",
      "display_name": "Dana Rivera",
      "email": "dana.rivera@example.com",
      "created_at": "2025-11-03T09:21:44.000Z",
      "updated_at": "2026-07-28T16:02:10.000Z"
    }
  ],
  "next_page_token": "eyJvcmdhbml6YXRpb2...",
  "has_more": true
}
```

<ResponseField name="object" type="string">
  Sempre `"list"`.
</ResponseField>

<ResponseField name="data" type="array">
  La pàgina de recursos, en un ordre estable i determinista.
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  Passeu-lo com a `page_token` a la sol·licitud següent per obtenir la pàgina següent.
  `null` quan no hi ha més resultats.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Indica si hi ha més resultats més enllà d'aquesta pàgina.
</ResponseField>

## Paràmetres de la sol·licitud

<ParamField query="limit" type="integer" default="25">
  Mida de la pàgina. Un enter entre 1 i 500. Els valors fora d'aquest interval retornen un
  `400` amb el codi `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  El `next_page_token` de la resposta anterior. Ometeu-lo per a la primera pàgina.
</ParamField>

No hi ha paràmetres de desplaçament (offset), ni recorregut cap a la pàgina anterior, ni recomptes totals exactes. Per comptar una col·lecció, cal recórrer-la.

<Note>
  **Excepció:** `GET /v1/cohorts/{id}/members` retorna com a màxim 50 files per
  pàgina, fins i tot quan sol·liciteu un `limit` superior. `has_more` i
  `next_page_token` continuen reflectint el romanent real del Cohort.
</Note>

Autentiqueu-vos amb qualsevol de les dues formes de credencial Basic; vegeu
[Quickstart](/ca/developers/v1/quickstart) (`apikey:secret` o `secret:`).
Establiu `BASE` amb el host regional de l'organització; vegeu
[Regions](/ca/developers/v1/regions).

## Recórrer una llista

Carregueu `LIVING_SECURITY_API_KEY` des del vostre gestor de secrets, com a la guia d'inici ràpid.
Aquest exemple requereix `entity:read`; és possible que la clau utilitzada a la guia de la primera sol·licitud
necessiti aquest permís addicional. Instal·leu `requests` per a Python o `jq` per a l'exemple
d'intèrpret d'ordres. Tots dos exemples fixen una versió, mantenen els filtres sense canvis i rebutgen les
redireccions. S'aturen davant d'errors i després de 1.000 pàgines, en lloc d'informar d'un
recorregut parcial com si fos complet. El temps d'espera de lectura de Python limita la inactivitat, no la durada total
de la tasca; imposeu un termini per a la tasca a la vostra integració.

Sol·liciteu pàgines fins que `next_page_token` sigui `null`. Preferiu `limit=500` per a
lectures massives, de manera que cobriu la col·lecció amb menys sol·licituds; vegeu els
[límits de velocitat](/ca/developers/v1/rate-limits).

<CodeGroup>
  ```bash cURL + jq theme={null}
  set -euo pipefail
  # US: BASE="https://api.us-east-1.livingsecurity.ai/v1"
  BASE="https://api.eu-west-1.livingsecurity.ai/v1"
  : "${LIVING_SECURITY_API_KEY:?Set LIVING_SECURITY_API_KEY}"
  TOKEN=""

  # Bound each run. Increase this page budget deliberately for larger collections.
  for ((page_number=1; page_number<=1000; page_number++)); do
    PARAMS=(--data-urlencode "limit=500" --data-urlencode "type=person")
    if [ -n "$TOKEN" ]; then
      PARAMS+=(--data-urlencode "page_token=$TOKEN")
    fi
    RESULT=$(curl --silent --show-error --fail-with-body \
      --connect-timeout 5 --max-time 30 --get \
      -u "apikey:$LIVING_SECURITY_API_KEY" \
      -H "Living-Security-Version: 2026-07-01" \
      --write-out '\n%{http_code}' "${PARAMS[@]}" "$BASE/entities")
    STATUS="${RESULT##*$'\n'}"
    PAGE="${RESULT%$'\n'*}"
    [ "$STATUS" = "200" ] || { echo "Unexpected HTTP status: $STATUS" >&2; exit 1; }
    jq -e 'has("next_page_token") and .object == "list" and (.data | type == "array") and
      ((.has_more == false and .next_page_token == null) or
       (.has_more == true and (.next_page_token | type == "string" and length > 0)))' \
      <<< "$PAGE" > /dev/null
    NEXT=$(jq -r '.next_page_token // empty' <<< "$PAGE")
    [ -z "$NEXT" ] || [ "$NEXT" != "$TOKEN" ] || { echo "Repeated page token" >&2; exit 1; }
    jq -r '.data[].id' <<< "$PAGE"
    [ -n "$NEXT" ] || exit 0
    TOKEN="$NEXT"
  done
  echo "Page budget exhausted; the collection is incomplete" >&2
  exit 1
  ```

  ```python Python theme={null}
  import os
  import requests

  # US: BASE = "https://api.us-east-1.livingsecurity.ai/v1"
  BASE = "https://api.eu-west-1.livingsecurity.ai/v1"
  AUTH = ("apikey", os.environ["LIVING_SECURITY_API_KEY"])

  def iter_entities(*, entity_type="person", max_pages=1000):
      if type(max_pages) is not int or max_pages < 1:
          raise ValueError("max_pages must be a positive integer")
      params = {"limit": 500, "type": entity_type}
      for _ in range(max_pages):
          response = requests.get(
              f"{BASE}/entities",
              auth=AUTH,
              params=params,
              headers={"Living-Security-Version": "2026-07-01"},
              timeout=(5, 30),
              allow_redirects=False,
          )
          try:
              response.raise_for_status()
              if response.status_code != 200:
                  raise RuntimeError("Unexpected response; check your regional API URL")
              page = response.json()
          finally:
              response.close()
          if (not isinstance(page, dict) or page.get("object") != "list"
                  or not isinstance(page.get("data"), list)
                  or type(page.get("has_more")) is not bool
                  or "next_page_token" not in page):
              raise RuntimeError("Invalid list response")
          token = page["next_page_token"]
          if ((page["has_more"] and (not isinstance(token, str) or not token))
                  or (not page["has_more"] and token is not None)):
              raise RuntimeError("Inconsistent list response")
          if token is not None and token == params.get("page_token"):
              raise RuntimeError("Repeated page token")
          yield from page["data"]
          if token is None:
              return
          params = {**params, "page_token": token}
      raise RuntimeError("Page budget exhausted; the collection is incomplete")

  if __name__ == "__main__":
      for entity in iter_entities():
          print(entity["id"])
  ```
</CodeGroup>

## Mantingueu els filtres estables durant la paginació

Els tokens de pàgina són cursors opacs i signats. Cada token està vinculat a
l'organització, al compte de servei autenticat, a la versió del contracte i al
conjunt exacte de filtres de la sol·licitud que l'ha generat. Canviar qualsevol d'aquests elements a mig recorregut (per
exemple, afegir un filtre `type` a la segona pàgina) retorna un `400` amb el codi
`invalid_request` al paràmetre `page_token`:

```json 400 Invalid request theme={null}
{
  "type": "https://docs.livingsecurity.com/developers/v1/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "detail": "page_token does not match this request's organization, credential, contract version, or filters.",
  "code": "invalid_request",
  "param": "page_token",
  "request_id": "req_...",
  "doc_url": "https://docs.livingsecurity.com/developers/v1/errors/invalid_request",
  "retryable": false
}
```

Per canviar els filtres, inicieu un recorregut nou des de la primera pàgina.

<Tip>
  Tracteu `page_token` com una cadena opaca: torneu-lo a passar exactament tal com l'heu rebut.
  No descodifiqueu, emmagatzemeu a llarg termini ni construïu tokens: el seu format intern
  pot canviar en qualsevol moment sense previ avís.
</Tip>

<Note>
  Els endpoints de llista rebutgen els paràmetres de consulta que no admeten amb un `400`
  `invalid_request` que indica el nom del paràmetre. Consulteu la referència de cada endpoint per
  conèixer els filtres admesos.
</Note>

## Gestioneu una col·lecció interrompuda o canviant

Aquests exemples no reintenten els errors automàticament. Per a `429`, respecteu `Retry-After`
i seguiu les [indicacions de reintent](/ca/developers/v1/rate-limits) acotades. Mantingueu la
mateixa regió, compte de servei, versió, filtres i l'últim token de pàgina processat correctament en
reintentar una lectura. Canviar les credencials no concedeix accés:
cada sol·licitud continua comprovant els permisos actuals.

Una lectura de diverses pàgines no és una instantània de la col·lecció. Les files poden canviar mentre
la recorreu. Processeu els recursos pel seu `id` estable i feu que les
escriptures posteriors siguin idempotents; un reinici pot tornar a retornar una fila. Si es rebutja un token,
examineu l'error `page_token` i corregiu la sol·licitud abans de reiniciar des de la
primera pàgina. No descarteu silenciosament les dades ja processades ni marqueu una
exportació interrompuda com a completa. Per obtenir totals exactes d'informes, utilitzeu el recurs
d'informes adequat en lloc de tractar un recorregut de llista en viu com una instantània.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.