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

> Gå gjennom lister i Living Security Public API ved hjelp av listekonvolutten, parameteren limit og ugjennomsiktige page_token-pekere.

Alle listeendepunkter i `/v1` returnerer den samme konvolutten og paginerer på
samme måte: tokenbasert og kun forover.

## Listekonvolutten

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

<ResponseField name="data" type="array">
  Siden med ressurser, i en stabil og deterministisk rekkefølge.
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  Send denne verdien som `page_token` i den neste forespørselen for å hente neste side.
  `null` når det ikke finnes flere resultater.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Angir om det finnes flere resultater utover denne siden.
</ResponseField>

## Forespørselsparametere

<ParamField query="limit" type="integer" default="25">
  Sidestørrelse. Et heltall mellom 1 og 500. Verdier utenfor dette området gir en
  `400` med koden `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  `next_page_token` fra det forrige svaret. Utelat den for den første siden.
</ParamField>

Det finnes ingen offset-parametere, ingen navigering til forrige side og ingen eksakte
totalantall. Hvis du vil telle en samling, må du gå gjennom den.

<Note>
  **Unntak:** `GET /v1/cohorts/{id}/members` returnerer maksimalt 50 rader per
  side, selv om du ber om en høyere `limit`. `has_more` og
  `next_page_token` gjenspeiler fortsatt det faktiske restantallet i kohorten.
</Note>

Autentiser med en av de to Basic-legitimasjonsformene – se
[hurtigstart](/no/developers/v1/quickstart) (`apikey:secret` eller `secret:`).
Sett `BASE` til organisasjonens regionale vert – se
[regioner](/no/developers/v1/regions).

## Gå gjennom en liste

Last inn `LIVING_SECURITY_API_KEY` fra hemmelighetsbehandleren din, som i hurtigstarten.
Dette eksemplet krever `entity:read`; nøkkelen som ble brukt i veiledningen for den første forespørselen,
kan trenge denne ekstra tilgangen. Installer `requests` for Python eller `jq` for skalleksemplet.
Begge eksemplene låser en versjon, holder filtrene uendret og avviser
omdirigeringer. De stopper ved feil og etter 1 000 sider i stedet for å rapportere en
delvis gjennomgang som fullført. Pythons lesetidsavbrudd begrenser inaktivitet, ikke den totale
varigheten til jobben; angi en tidsfrist for jobben i integrasjonen din.

Be om sider til `next_page_token` er `null`. Foretrekk `limit=500` for bulkavlesing, slik at du dekker samlingen med færre forespørsler – se
[grenser for forespørselsrate](/no/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>

## Hold filtrene stabile under paginering

Sidetokener er ugjennomsiktige, signerte pekere. Hvert token er bundet til
organisasjonen, den autentiserte tjenestekontoen, kontraktsversjonen og det
eksakte filtersettet i forespørselen som produserte det. Hvis du endrer noe av dette midt i en gjennomgang – for
eksempel ved å legge til et `type`-filter på side to – returneres en `400` med koden
`invalid_request` for parameteren `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
}
```

Hvis du vil endre filtre, må du starte en ny gjennomgang fra den første siden.

<Tip>
  Behandle `page_token` som en ugjennomsiktig streng: send den tilbake nøyaktig slik du mottok den.
  Ikke dekod, lagre langsiktig eller konstruer tokener – det interne formatet
  kan endres når som helst uten varsel.
</Tip>

<Note>
  Listeendepunkter avviser spørringsparametere de ikke støtter, med en `400`
  `invalid_request` som angir parameteren. Se referansen for hvert endepunkt for å finne
  hvilke filtre som støttes.
</Note>

## Håndter en avbrutt eller skiftende samling

Disse eksemplene forsøker ikke automatisk på nytt ved feil. For `429` må du følge `Retry-After`
og den avgrensede [veiledningen for nye forsøk](/no/developers/v1/rate-limits). Bruk
samme region, tjenestekonto, versjon, filtre og sist vellykket behandlede
sidetoken når du prøver en lesing på nytt. Bytte av legitimasjon gir ikke tilgang:
hver forespørsel kontrollerer fortsatt gjeldende tillatelser.

En lesing over flere sider er ikke et øyeblikksbilde av samlingen. Rader kan endres mens
du går gjennom den. Behandle ressurser ut fra den stabile `id` og gjør nedstrøms
skriving idempotent; en omstart kan returnere en rad på nytt. Hvis et token avvises,
undersøk feilen `page_token` og rett opp forespørselen før du starter på nytt fra
side én. Ikke forkast tidligere behandlede data i det stille, og ikke marker en
avbrutt eksport som fullført. For eksakte rapporteringstotaler bør du bruke den aktuelle
rapporteringsressursen i stedet for å behandle en levende listegjennomgang som et øyeblikksbilde.


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