> ## 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، وعقد الاستجابة 429، وكيفية إعادة المحاولة باستخدام Retry-After.

تفرض واجهة `/v1` البرمجية حدَّين مستقلين للطلبات. يُرفض الطلب
إذا استُنفد أي من الحدَّين.

| الحد | ينطبق على |
| - | - |
| لكل مفتاح API | كل طلب يقدّم ذلك المفتاح، من أي عنوان |
| لكل عنوان IP للعميل | كل طلب من ذلك العنوان، سواء كان موثَّقًا أم لا |

يتبع الحد المخصص لكل مفتاح المفتاحَ أينما استُخدم. أما الحد المخصص لكل عنوان IP
فهو الحد الوحيد لحركة البيانات غير الموثَّقة، وسقف ثانٍ لحركة البيانات
الموثَّقة.

<Note>
  تُطبَّق الحدود قبل المصادقة، لذا فإن الطلبات ذات بيانات الاعتماد غير الصالحة أو
  المفقودة تُحتسب أيضًا ضمن حد المصدر. الحدود الرقمية الدقيقة
  يحددها المشغّل وقد تتغير، ويمثّل عقد الاستجابة الوارد أدناه
  الواجهة الثابتة التي ينبغي البناء عليها.
</Note>

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

## الاستجابة 429

عند استنفاد أحد الحدود، تُرجع الواجهة البرمجية `429 Too Many Requests` مع
ترويسة `Retry-After` (بالثواني) ومتن تفاصيل المشكلة القياسي:

```json 429 Too Many Requests theme={null}
{
  "type": "https://docs.livingsecurity.com/developers/v1/errors/rate_limited",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Retry after the Retry-After interval.",
  "code": "rate_limited",
  "request_id": "req_...",
  "doc_url": "https://docs.livingsecurity.com/developers/v1/errors/rate_limited",
  "retryable": true
}
```

لا توضح الاستجابة أي الحدَّين قد استُنفد. تعامل مع كل استجابة `429`
بالطريقة نفسها: انتظر، ثم أعد المحاولة.

## التعامل مع استجابات 429

<Steps>
  <Step title="الالتزام بـ Retry-After">
    انتظر مدة لا تقل عن عدد الثواني الوارد في ترويسة `Retry-After` قبل
    إعادة المحاولة. إن إعادة المحاولة قبل ذلك تستهلك الحد مجددًا في طلبات
    سيتم رفضها.
  </Step>

  <Step title="التراجع الأسي عند تكرار الرفض">
    إذا رُفضت إعادة المحاولة مرة أخرى، فزد مدة التراجع وأضف تباينًا عشوائيًا
    حتى لا تعيد المهام المتوازية المحاولة في الوقت نفسه. لا تقلّص قيمة `Retry-After` التي يحددها الخادم لتناسب حدًا
    محليًا. وإذا طلب منك الخادم الانتظار مدة أطول مما تسمح به ميزانية إعادة المحاولة لديك،
    فتوقف وجدوِل العمل لوقت لاحق.
  </Step>

  <Step title="تسوية معدل الطلبات">
    فضّل معدل طلبات ثابتًا على الدفعات المفاجئة. بالنسبة إلى عمليات القراءة المجمّعة، استخدم الحد الأقصى
    لحجم الصفحة (`limit=500`) لتغطية المجموعة بعدد أقل من الطلبات — راجع
    [ترقيم الصفحات](/ar/developers/v1/pagination). وعند تشغيل عدة عمليات تصفح للقوائم
    بالتوازي (مثل جداول Power BI)، أبقِ التزامن معتدلًا والتزم
    بـ `Retry-After` حتى لا يتسبب رفض مؤقت بالاستجابة 429 في فشل عملية التحديث بالكامل.
  </Step>
</Steps>

يعيد هذا المثال المحاولة فقط عند استجابات `429` لطلب **GET**، بحد أقصى
خمس محاولات وبحد أقصى 60 ثانية من الانتظار بين المحاولات. ويتوقف
فورًا عند الأخطاء الأخرى. وتنتقل مهلات الشبكة إلى المستدعي. اضبط
المهلات وميزانيات إعادة المحاولة بما يناسب حمل العمل لديك. يفسّر `requests` مهلة
القراءة على أنها الحد الأقصى لمدة الخمول أثناء استلام البيانات، وليست مهلة إجمالية.

حمّل `LIVING_SECURITY_API_KEY` من مدير الأسرار لديك. ثبّت `requests`
قبل تشغيل هذا المثال. استدعِ `get_with_retry("/organization")` لاستخدامه.

```python Python theme={null}
import os
import random
import time
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 get_with_retry(path, params=None, max_attempts=5):
    if not 1 <= max_attempts <= 5:
        raise ValueError("max_attempts must be between 1 and 5")
    for attempt in range(max_attempts):
        response = requests.get(
            f"{BASE}{path}", auth=AUTH, params=params,
            headers={"Living-Security-Version": "2026-07-01"},
            timeout=(5, 30), allow_redirects=False,
        )
        if response.status_code != 429:
            response.raise_for_status()
            if not 200 <= response.status_code < 300:
                raise RuntimeError("Unexpected redirect; check your regional API URL")
            return response

        # The API returns Retry-After as a whole number of seconds.
        raw_wait = response.headers.get("Retry-After", "")
        request_id = response.headers.get("Request-Id", "unknown")
        response.close()
        if attempt == max_attempts - 1:
            raise RuntimeError(f"Retry budget exhausted; request_id={request_id}")
        if not raw_wait.isascii() or not raw_wait.isdigit() or len(raw_wait) > 6:
            raise RuntimeError(f"Invalid Retry-After; request_id={request_id}")

        wait = max(int(raw_wait), min(2 ** attempt, 30))
        delay = wait + random.uniform(0, 1)
        if delay > 60:
            raise RuntimeError(f"Retry-After exceeds wait budget; request_id={request_id}")
        time.sleep(delay)
```

لا تنسخ هذه الحلقة حول عملية كتابة. فقد تعني مهلة تنتهي بعد عملية كتابة
أن الخادم أتمّها قبل انقطاع الاتصال. لا تكرر عملية الكتابة إلا
إذا كان مرجع تلك العملية يوثّق صراحةً إمكانية تكرارها بأمان (idempotency)، مع الإبقاء على
المفتاح نفسه والحمولة نفسها. وفيما عدا ذلك، تحقق من حالة المورد قبل المحاولة مجددًا.

## جدول التحديث الموصى به

حدِّد وتيرة التحديث بما يتناسب مع حد المفتاح لديك وحجم الصفحة. إن التحميل التاريخي الكامل
لمجموعة كبيرة تكلفة تُدفع مرة واحدة؛ فضّل النوافذ التدريجية
لعمليات التحديث في الحالة المستقرة بحيث تبقى كل عملية ضمن الحد بفارق مريح. اضبط دائمًا
`limit=500` صراحةً — فالقيمة الافتراضية 25 تضاعف عدد الطلبات.


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