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

# Paginacja

> Przeglądanie list w Living Security Public API za pomocą koperty listy, parametru limit oraz nieprzezroczystych kursorów page_token.

Każdy punkt końcowy listy `/v1` zwraca tę samą kopertę i stosuje ten sam
sposób paginacji: oparty na tokenach, tylko do przodu.

## Koperta listy

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

<ResponseField name="data" type="array">
  Strona zasobów w stałej, deterministycznej kolejności.
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  Przekaż tę wartość jako `page_token` w następnym żądaniu, aby pobrać kolejną stronę.
  `null`, gdy nie ma już więcej wyników.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Informuje, czy poza bieżącą stroną istnieją kolejne wyniki.
</ResponseField>

## Parametry żądania

<ParamField query="limit" type="integer" default="25">
  Rozmiar strony. Liczba całkowita z zakresu od 1 do 500. Wartości spoza tego zakresu powodują zwrócenie
  `400` z kodem `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  Wartość `next_page_token` z poprzedniej odpowiedzi. Pomiń ją przy pobieraniu pierwszej strony.
</ParamField>

Nie ma parametrów przesunięcia (offset), przechodzenia do poprzedniej strony ani dokładnych
łącznych liczności. Aby policzyć elementy kolekcji, należy ją przejść w całości.

<Note>
  **Wyjątek:** `GET /v1/cohorts/{id}/members` zwraca co najwyżej 50 wierszy na
  stronę, nawet jeśli zażądano wyższej wartości `limit`. `has_more` i
  `next_page_token` nadal odzwierciedlają rzeczywistą pozostałą część Kohorty.
</Note>

Uwierzytelnianie można przeprowadzić za pomocą dowolnej z dwóch postaci poświadczeń Basic — zobacz
[Szybki start](/pl/developers/v1/quickstart) (`apikey:secret` lub `secret:`).
Ustaw `BASE` na regionalny host organizacji — zobacz
[Regiony](/pl/developers/v1/regions).

## Przechodzenie przez listę

Wczytaj `LIVING_SECURITY_API_KEY` z menedżera sekretów, tak jak w szybkim starcie.
Ten przykład wymaga `entity:read`; klucz użyty w przewodniku dotyczącym pierwszego żądania może
wymagać tego dodatkowego uprawnienia. Zainstaluj `requests` dla przykładu w Pythonie lub `jq` dla przykładu
w powłoce. Oba przykłady przypinają wersję, nie zmieniają filtrów i odrzucają
przekierowania. Zatrzymują się po błędach oraz po 1000 stronach, zamiast zgłaszać
częściowe przejście jako zakończone. Limit czasu odczytu w Pythonie ogranicza czas bezczynności, a nie łączny
czas trwania zadania; w swojej integracji ustaw limit czasu dla całego zadania.

Pobieraj kolejne strony, aż `next_page_token` przyjmie wartość `null`. Do odczytów
zbiorczych preferuj `limit=500`, aby objąć kolekcję mniejszą liczbą żądań — zobacz
[limity żądań](/pl/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>

## Zachowaj stałe filtry podczas paginacji

Tokeny stron to nieprzezroczyste, podpisane kursory. Każdy token jest powiązany z
organizacją, uwierzytelnionym kontem usługi, wersją kontraktu oraz
dokładnym zestawem filtrów żądania, które go wygenerowało. Zmiana któregokolwiek z tych elementów w trakcie przechodzenia — na
przykład dodanie filtra `type` na drugiej stronie — powoduje zwrócenie `400` z kodem
`invalid_request` dla parametru `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
}
```

Aby zmienić filtry, rozpocznij nowe przejście od pierwszej strony.

<Tip>
  Traktuj `page_token` jako nieprzezroczysty ciąg znaków: przekazuj go z powrotem dokładnie w otrzymanej postaci.
  Nie dekoduj go, nie przechowuj długoterminowo ani nie konstruuj tokenów — ich wewnętrzny format
  może ulec zmianie w dowolnym momencie bez powiadomienia.
</Tip>

<Note>
  Punkty końcowe list odrzucają nieobsługiwane parametry zapytania, zwracając `400`
  `invalid_request` ze wskazaniem nazwy parametru. Obsługiwane filtry sprawdź w dokumentacji referencyjnej
  każdego punktu końcowego.
</Note>

## Obsługa przerwanej lub zmieniającej się kolekcji

Te przykłady nie ponawiają błędów automatycznie. W przypadku `429` uwzględnij `Retry-After`
i postępuj zgodnie z ograniczonymi [wskazówkami dotyczącymi ponawiania](/pl/developers/v1/rate-limits). Podczas ponawiania odczytu zachowaj
ten sam region, konto usługi, wersję, filtry oraz token ostatniej pomyślnie przetworzonej
strony. Zmiana poświadczeń nie przyznaje dostępu:
każde żądanie nadal sprawdza bieżące uprawnienia.

Odczyt obejmujący wiele stron nie jest migawką kolekcji. Wiersze mogą się zmieniać w trakcie
jej przechodzenia. Przetwarzaj zasoby według ich stałego `id` i zapewnij idempotentność
zapisów w systemach docelowych; po ponownym uruchomieniu wiersz może zostać zwrócony ponownie. Jeśli token zostanie odrzucony,
sprawdź błąd `page_token` i popraw żądanie, zanim rozpoczniesz od
pierwszej strony. Nie odrzucaj po cichu wcześniej przetworzonych danych ani nie oznaczaj
przerwanego eksportu jako zakończonego. Aby uzyskać dokładne sumy raportowe, użyj odpowiedniego
zasobu raportowego zamiast traktować przechodzenie przez aktywną listę jak migawkę.


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