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

# ترقيم الصفحات

> تصفّح قوائم واجهة Living Security Public API باستخدام غلاف القائمة والمعلمة limit ومؤشرات page_token المعتمة.

تعرض كل نقطة نهاية قائمة في `/v1` الغلاف نفسه وتعتمد طريقة ترقيم الصفحات نفسها:
قائمة على الرموز المميزة وللأمام فقط.

## غلاف القائمة

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

## معلمات الطلب

<ParamField query="limit" type="integer" default="25">
  حجم الصفحة. عدد صحيح بين 1 و500. تؤدي القيم الواقعة خارج هذا النطاق إلى إرجاع
  `400` مع الرمز `invalid_request`.
</ParamField>

<ParamField query="page_token" type="string">
  قيمة `next_page_token` من الاستجابة السابقة. احذفها عند طلب الصفحة الأولى.
</ParamField>

لا توجد معلمات إزاحة (offset)، ولا إمكانية للرجوع إلى الصفحة السابقة، ولا أعداد إجمالية دقيقة. لحساب عدد عناصر مجموعة ما، يلزم المرور عليها بالكامل.

<Note>
  **استثناء:** يعرض `GET /v1/cohorts/{id}/members` 50 صفًا على الأكثر في كل
  صفحة حتى عند طلب قيمة أعلى لـ `limit`. وتظل `has_more` و
  `next_page_token` تعكسان الباقي الفعلي من المجموعة.
</Note>

صادِق باستخدام أي من شكلَي بيانات اعتماد Basic — راجع
[البدء السريع](/ar/developers/v1/quickstart) (`apikey:secret` أو `secret:`).
اضبط `BASE` على المضيف الإقليمي للمؤسسة — راجع
[المناطق](/ar/developers/v1/regions).

## المرور على قائمة

حمّل `LIVING_SECURITY_API_KEY` من مدير الأسرار لديك كما في البدء السريع.
يتطلب هذا المثال `entity:read`؛ وقد يحتاج المفتاح المستخدم في دليل الطلب الأول
إلى هذا الإذن الإضافي. ثبّت `requests` لمثال Python أو `jq` لمثال الصدفة (shell).
يثبّت المثالان إصدارًا محددًا، ويُبقيان عوامل التصفية دون تغيير، ويرفضان
عمليات إعادة التوجيه. ويتوقفان عند حدوث الأخطاء وبعد 1,000 صفحة بدلًا من الإبلاغ عن
مرور جزئي على أنه مكتمل. يحدّ مهلة القراءة في Python فترة الخمول وليس المدة
الإجمالية للمهمة؛ لذا عيّن مهلة نهائية للمهمة في تكاملك.

اطلب الصفحات إلى أن تصبح قيمة `next_page_token` هي `null`. يُفضَّل استخدام `limit=500` في عمليات
القراءة الكبيرة لتغطية المجموعة بعدد أقل من الطلبات — راجع
[حدود المعدل](/ar/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>

## حافظ على ثبات عوامل التصفية أثناء ترقيم الصفحات

رموز الصفحات هي مؤشرات معتمة وموقّعة. يرتبط كل رمز مميز بالمؤسسة،
وحساب الخدمة الذي جرت مصادقته، وإصدار العقد، ومجموعة عوامل التصفية
الدقيقة للطلب الذي أنتجه. يؤدي تغيير أي منها أثناء المرور — مثل
إضافة عامل تصفية `type` في الصفحة الثانية — إلى إرجاع `400` مع الرمز
`invalid_request` على المعلمة `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
}
```

لتغيير عوامل التصفية، ابدأ مرورًا جديدًا من الصفحة الأولى.

<Tip>
  تعامل مع `page_token` على أنه سلسلة معتمة: أعِده تمامًا كما استلمته.
  لا تفكّ ترميزه، ولا تخزّنه لمدة طويلة، ولا تنشئ رموزًا بنفسك — إذ قد يتغير
  تنسيقها الداخلي في أي وقت دون إشعار.
</Tip>

<Note>
  ترفض نقاط نهاية القوائم معلمات الاستعلام غير المدعومة بإرجاع `400`
  `invalid_request` يسمّي المعلمة. راجع مرجع كل نقطة نهاية لمعرفة
  عوامل التصفية المدعومة فيها.
</Note>

## التعامل مع مجموعة متقطعة أو متغيرة

لا تعيد هذه الأمثلة محاولة الطلبات تلقائيًا عند حدوث الأخطاء. بالنسبة إلى `429`، التزم بـ `Retry-After`
واتبع [إرشادات إعادة المحاولة](/ar/developers/v1/rate-limits) المحدودة. احتفظ بالمنطقة
وحساب الخدمة والإصدار وعوامل التصفية نفسها، وبآخر رمز صفحة جرت معالجته بنجاح عند إعادة محاولة
عملية قراءة. إن تغيير بيانات الاعتماد لا يمنح صلاحية وصول:
إذ يتحقق كل طلب من الأذونات الحالية.

القراءة متعددة الصفحات ليست لقطة ثابتة للمجموعة. فقد تتغير الصفوف أثناء
المرور عليها. عالج الموارد بحسب `id` الثابت الخاص بها واجعل عمليات
الكتابة اللاحقة متماثلة الأثر (idempotent)؛ فقد تعيد إعادة التشغيل صفًا مرة أخرى. إذا رُفض رمز مميز،
فافحص الخطأ `page_token` وصحّح الطلب قبل إعادة البدء من
الصفحة الأولى. لا تتجاهل البيانات التي سبقت معالجتها بصمت ولا تعتبر
عملية تصدير متقطعة مكتملة. وللحصول على إجماليات دقيقة للتقارير، استخدم
مورد التقارير المناسب بدلًا من اعتبار المرور الحي على القائمة لقطة ثابتة.


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