> ## 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.

# Paginering

> Doorloop lijsten van de Living Security Public API met de lijstenvelop, de parameter limit en ondoorzichtige page_token-cursors.

Elk `/v1`-lijsteindpunt retourneert dezelfde envelop en pagineert op dezelfde
manier: tokengebaseerd en uitsluitend voorwaarts.

## De lijstenvelop

```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">
  Altijd `"list"`.
</ResponseField>

<ResponseField name="data" type="array">
  De pagina met resources, in een stabiele, deterministische volgorde.
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  Geef dit mee als `page_token` bij het volgende verzoek om de volgende pagina op te halen.
  `null` wanneer er geen resultaten meer zijn.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Geeft aan of er na deze pagina nog meer resultaten bestaan.
</ResponseField>

## Verzoekparameters

<ParamField query="limit" type="integer" default="25">
  Paginagrootte. Een geheel getal van 1 tot en met 500. Waarden buiten dit bereik leiden tot een
  `400` met de code `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  De `next_page_token` uit het vorige antwoord. Laat deze parameter weg voor de eerste pagina.
</ParamField>

Er zijn geen offsetparameters, geen navigatie naar de vorige pagina en geen exacte
totaalaantallen. Om een verzameling te tellen, doorloopt u deze volledig.

<Note>
  **Uitzondering:** `GET /v1/cohorts/{id}/members` retourneert maximaal 50 rijen per
  pagina, ook wanneer u een hogere `limit` opgeeft. `has_more` en
  `next_page_token` geven nog steeds het werkelijke restant van de Cohort weer.
</Note>

Authenticeer met een van beide Basic-referentievormen; zie de
[Quickstart](/nl/developers/v1/quickstart) (`apikey:secret` of `secret:`).
Stel `BASE` in op de regionale host van de organisatie; zie
[Regio's](/nl/developers/v1/regions).

## Een lijst doorlopen

Laad `LIVING_SECURITY_API_KEY` uit uw secretmanager, zoals in de Quickstart.
Dit voorbeeld vereist `entity:read`; voor de sleutel die is gebruikt voor de handleiding voor het eerste verzoek
kan deze aanvullende machtiging nodig zijn. Installeer `requests` voor Python of `jq` voor het shellvoorbeeld.
Beide voorbeelden leggen een versie vast, laten filters ongewijzigd en weigeren
redirects. Ze stoppen bij fouten en na 1.000 pagina's, in plaats van een
gedeeltelijke doorloop als volledig te rapporteren. De leestimeout van Python begrenst inactiviteit, niet de totale
duur van de taak; stel in uw integratie een deadline voor de taak in.

Vraag pagina's op totdat `next_page_token` gelijk is aan `null`. Geef de voorkeur aan `limit=500` voor bulk-
leesacties, zodat u de verzameling met minder verzoeken doorloopt; zie
[rate limits](/nl/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>

## Houd filters stabiel tijdens het pagineren

Paginatokens zijn ondoorzichtige, ondertekende cursors. Elk token is gebonden aan de
organisatie, het geauthenticeerde serviceaccount, de contractversie en de
exacte filterset van het verzoek waarmee het is aangemaakt. Als u een van deze tijdens een doorloop wijzigt, bijvoorbeeld
door op de tweede pagina een `type`-filter toe te voegen, ontvangt u een `400` met de code
`invalid_request` voor de parameter `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
}
```

Om filters te wijzigen, start u een nieuwe doorloop vanaf de eerste pagina.

<Tip>
  Behandel `page_token` als een ondoorzichtige tekenreeks: geef deze exact terug zoals u hem hebt ontvangen.
  Decodeer, bewaar of construeer tokens niet voor langere tijd; hun interne indeling
  kan op elk moment zonder voorafgaande kennisgeving veranderen.
</Tip>

<Note>
  Lijsteindpunten weigeren queryparameters die ze niet ondersteunen met een `400`
  `invalid_request` waarin de parameter wordt genoemd. Raadpleeg de referentie van elk eindpunt voor
  de ondersteunde filters.
</Note>

## Een onderbroken of veranderende verzameling afhandelen

Deze voorbeelden proberen fouten niet automatisch opnieuw. Houd bij `429` rekening met `Retry-After`
en volg de begrensde [richtlijnen voor opnieuw proberen](/nl/developers/v1/rate-limits). Gebruik bij het opnieuw proberen van een leesactie dezelfde
regio, hetzelfde serviceaccount, dezelfde versie, dezelfde filters en het laatst succesvol verwerkte
paginatoken. Het wijzigen van referenties verleent geen toegang:
elk verzoek controleert nog steeds de actuele machtigingen.

Een leesactie over meerdere pagina's is geen momentopname van de verzameling. Rijen kunnen wijzigen terwijl
u de verzameling doorloopt. Verwerk resources op basis van hun stabiele `id` en maak downstream-
schrijfacties idempotent; na een herstart kan een rij opnieuw worden geretourneerd. Als een token wordt geweigerd,
controleer dan de `page_token`-fout en corrigeer het verzoek voordat u opnieuw begint vanaf
de eerste pagina. Verwijder eerder verwerkte gegevens niet stilzwijgend en markeer een
onderbroken export niet als voltooid. Gebruik voor exacte rapportagetotalen de juiste
rapportageresource in plaats van een live lijstdoorloop als momentopname te beschouwen.


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