> ## 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å igenom listor i Living Security Public API med listenveloppen, parametern limit och ogenomskinliga page_token-markörer.

Varje `/v1`-listslutpunkt returnerar samma envelopp och paginerar på samma
sätt: tokenbaserat och endast framåt.

## Listenveloppen

```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">
  Sidan med resurser, i en stabil och deterministisk ordning.
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  Skicka detta som `page_token` i nästa begäran för att hämta följande sida.
  `null` när det inte finns fler resultat.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Anger om det finns fler resultat utöver den här sidan.
</ResponseField>

## Begäransparametrar

<ParamField query="limit" type="integer" default="25">
  Sidstorlek. Ett heltal mellan 1 och 500. Värden utanför detta intervall ger
  `400` med koden `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  `next_page_token` från föregående svar. Utelämna den för den första sidan.
</ParamField>

Det finns inga offsetparametrar, ingen bakåtnavigering mellan sidor och inga exakta
totalantal. Om du vill räkna en samling måste du gå igenom den.

<Note>
  **Undantag:** `GET /v1/cohorts/{id}/members` returnerar högst 50 rader per
  sida, även om du begär ett högre `limit`. `has_more` och
  `next_page_token` återspeglar fortfarande den verkliga återstoden av kohorten.
</Note>

Autentisera med någon av de två Basic-uppgiftsformerna – se
[Snabbstart](/sv/developers/v1/quickstart) (`apikey:secret` eller `secret:`).
Ange `BASE` som organisationens regionala värd – se
[Regioner](/sv/developers/v1/regions).

## Gå igenom en lista

Läs in `LIVING_SECURITY_API_KEY` från din hemlighetshanterare på samma sätt som i snabbstarten.
Det här exemplet kräver `entity:read`; nyckeln som användes i guiden för den första begäran
kan behöva den ytterligare behörigheten. Installera `requests` för Python eller `jq` för
shell-exemplet. Båda exemplen låser en version, behåller filtren oförändrade och avvisar
omdirigeringar. De avbryts vid fel och efter 1 000 sidor i stället för att rapportera en
ofullständig genomgång som slutförd. Pythons läs-timeout begränsar inaktivitet, inte den totala
körtiden; ange en tidsgräns för hela jobbet i din integration.

Begär sidor tills `next_page_token` är `null`. Föredra `limit=500` för massläsning så
att du täcker samlingen med färre begäranden – se
[hastighetsbegränsningar](/sv/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>

## Håll filtren stabila under paginering

Sidtokens är ogenomskinliga, signerade markörer. Varje token är knuten till
organisationen, det autentiserade tjänstekontot, kontraktsversionen och den
exakta uppsättning filter som gällde för begäran som skapade den. Om du ändrar något av dessa under en genomgång – till
exempel genom att lägga till ett `type`-filter på sida två – returneras ett `400` med koden
`invalid_request` för parametern `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 du vill ändra filter startar du en ny genomgång från första sidan.

<Tip>
  Behandla `page_token` som en ogenomskinlig sträng: skicka tillbaka den exakt som du fick den.
  Avkoda, lagra långsiktigt eller konstruera inte tokens – deras interna format
  kan ändras när som helst utan föregående meddelande.
</Tip>

<Note>
  Listslutpunkter avvisar frågeparametrar som de inte stöder med ett `400`
  `invalid_request` som anger parametern. Kontrollera varje slutpunkts referens för att se
  vilka filter som stöds.
</Note>

## Hantera en avbruten eller föränderlig samling

Dessa exempel försöker inte automatiskt igen vid fel. Vid `429`, följ `Retry-After`
och de begränsade [riktlinjerna för omförsök](/sv/developers/v1/rate-limits). Behåll
samma region, tjänstekonto, version, filter och senast framgångsrikt bearbetade
sidtoken när du försöker en läsning igen. Att byta autentiseringsuppgifter ger inte åtkomst:
varje begäran kontrollerar fortfarande aktuella behörigheter.

En läsning över flera sidor är inte en ögonblicksbild av samlingen. Rader kan ändras medan
du går igenom den. Bearbeta resurser utifrån deras stabila `id` och gör efterföljande
skrivningar idempotenta; en omstart kan returnera en rad igen. Om en token avvisas,
granska felet `page_token` och åtgärda begäran innan du startar om från
första sidan. Kassera inte tyst tidigare bearbetade data och markera inte en
avbruten export som slutförd. För exakta rapporteringstotaler ska du använda lämplig
rapporteringsresurs i stället för att behandla en live-genomgång av en lista som en ögonblicksbild.


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