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

# Pagination

> list envelope, limit पैरामीटर और अपारदर्शी page_token कर्सर का उपयोग करके Living Security Public API की सूचियों को क्रमवार प्राप्त करें।

Living Security के प्रत्येक `/v1` list endpoint का envelope समान होता है और वे एक ही तरह से पेजिनेशन करते हैं:
टोकन-आधारित और केवल आगे की दिशा में।

## The list envelope

```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">
  हमेशा `"list"`।
</ResponseField>

<ResponseField name="data" type="array">
  संसाधनों का पेज, एक स्थिर और निर्धारित क्रम में।
</ResponseField>

<ResponseField name="next_page_token" type="string | null">
  अगला पेज प्राप्त करने के लिए अगले अनुरोध में इसे `page_token` के रूप में पास करें।
  जब और परिणाम न हों, तो `null`।
</ResponseField>

<ResponseField name="has_more" type="boolean">
  क्या इस पेज के बाद भी और परिणाम उपलब्ध हैं।
</ResponseField>

## Request parameters

<ParamField query="limit" type="integer" default="25">
  पेज का आकार। 1 से 500 के बीच का पूर्णांक। इस सीमा से बाहर के मान कोड `invalid_request` के साथ `400` लौटाते हैं।
</ParamField>

<ParamField query="page_token" type="string">
  पिछले response से प्राप्त `next_page_token`। पहले पेज के लिए इसे छोड़ दें।
</ParamField>

इसमें कोई offset पैरामीटर नहीं हैं, पिछले पेज पर जाने की सुविधा नहीं है, और कुल संख्या की सटीक गणना उपलब्ध नहीं है। किसी संग्रह की गणना करने के लिए उसे क्रमवार पूरा पढ़ें।

<Note>
  **अपवाद:** `GET /v1/cohorts/{id}/members` प्रति पेज अधिकतम 50 पंक्तियाँ लौटाता है, भले ही आप अधिक `limit` का अनुरोध करें। `has_more` और `next_page_token` फिर भी Cohort के वास्तविक शेष भाग को दर्शाते हैं।
</Note>

किसी भी Basic credential रूप से प्रमाणीकृत करें — देखें
[Quickstart](/hi/developers/v1/quickstart) (`apikey:secret` या `secret:`)।
`BASE` को संगठन के क्षेत्रीय होस्ट पर सेट करें — देखें
[Regions](/hi/developers/v1/regions)।

## Walking a list

Quickstart की तरह अपने secret manager से `LIVING_SECURITY_API_KEY` लोड करें।
इस उदाहरण के लिए `entity:read` आवश्यक है; पहले अनुरोध की मार्गदर्शिका में उपयोग की गई key को यह अतिरिक्त अनुमति देनी पड़ सकती है। Python के लिए `requests` या shell उदाहरण के लिए `jq` इंस्टॉल करें। दोनों उदाहरण एक संस्करण पिन करते हैं, फ़िल्टर अपरिवर्तित रखते हैं और redirect अस्वीकार करते हैं। वे त्रुटियों पर और 1,000 पेज के बाद रुक जाते हैं, ताकि अधूरे walk को पूर्ण के रूप में रिपोर्ट न किया जाए। Python का read timeout निष्क्रियता की अवधि को सीमित करता है, कुल कार्य-अवधि को नहीं; अपने इंटीग्रेशन में कार्य की समय-सीमा निर्धारित करें।

तब तक पेज का अनुरोध करते रहें जब तक `next_page_token` का मान `null` न हो जाए। बल्क रीड के लिए `limit=500` को प्राथमिकता दें, ताकि कम अनुरोधों में पूरा संग्रह कवर हो — देखें
[rate limits](/hi/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>

## Keep filters stable while paginating

पेज टोकन अपारदर्शी, हस्ताक्षरित कर्सर होते हैं। प्रत्येक टोकन उस अनुरोध के संगठन, प्रमाणीकृत service account, contract संस्करण और सटीक फ़िल्टर समूह से बंधा होता है जिसने उसे उत्पन्न किया। walk के बीच में इनमें से किसी को भी बदलने पर — उदाहरण के लिए, दूसरे पेज पर `type` फ़िल्टर जोड़ने पर — `page_token` पैरामीटर पर कोड `invalid_request` के साथ `400` लौटता है:

```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
}
```

फ़िल्टर बदलने के लिए, पहले पेज से नया walk शुरू करें।

<Tip>
  `page_token` को अपारदर्शी स्ट्रिंग मानें: इसे ठीक उसी रूप में वापस पास करें जिस रूप में यह प्राप्त हुआ। टोकन को decode न करें, दीर्घकालिक रूप से संग्रहीत न करें और न ही स्वयं बनाएँ — उनका आंतरिक प्रारूप बिना सूचना के किसी भी समय बदल सकता है।
</Tip>

<Note>
  List endpoint उन query पैरामीटर को अस्वीकार करते हैं जिन्हें वे समर्थित नहीं करते, और उस पैरामीटर का नाम बताते हुए `400` `invalid_request` लौटाते हैं। समर्थित फ़िल्टर के लिए प्रत्येक endpoint का संदर्भ देखें।
</Note>

## Handle an interrupted or changing collection

ये उदाहरण त्रुटियों को स्वचालित रूप से पुनः प्रयास नहीं करते। `429` के लिए `Retry-After` का पालन करें और सीमित [retry guidance](/hi/developers/v1/rate-limits) का अनुसरण करें। रीड को पुनः प्रयास करते समय वही region, service account, संस्करण, फ़िल्टर और अंतिम सफलतापूर्वक संसाधित पेज टोकन रखें। credentials बदलने से एक्सेस नहीं मिल जाता: प्रत्येक अनुरोध में वर्तमान अनुमतियों की जाँच फिर भी होती है।

बहु-पेज रीड संग्रह का स्नैपशॉट नहीं होता। आपके traverse करते समय पंक्तियाँ बदल सकती हैं। संसाधनों को उनके स्थिर `id` द्वारा संसाधित करें और डाउनस्ट्रीम राइट्स को idempotent बनाएँ; पुनः आरंभ करने पर कोई पंक्ति फिर से लौट सकती है। यदि कोई टोकन अस्वीकार किया जाता है, तो `page_token` त्रुटि की जाँच करें और पहले पेज से पुनः आरंभ करने से पहले अनुरोध को सुधारें। पहले संसाधित डेटा को चुपचाप न हटाएँ और न ही बाधित export को पूर्ण के रूप में चिह्नित करें। रिपोर्टिंग के सटीक कुल योग के लिए, लाइव सूची traversal को स्नैपशॉट मानने के बजाय उपयुक्त reporting resource का उपयोग करें।


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