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

API `/v1` застосовує два незалежні ліміти запитів. Запит відхиляється,
якщо вичерпано будь-який із них.

| Ліміт | Застосовується до |
| - | - |
| На API-ключ | Кожного запиту з цим ключем, з будь-якої адреси |
| На IP-адресу клієнта | Кожного запиту з цієї адреси, автентифікованого чи ні |

Ліміт на ключ діє скрізь, де використовується цей ключ. Ліміт на IP-адресу є
єдиним лімітом для неавтентифікованого трафіку та другою межею для
автентифікованого трафіку.

<Note>
  Ліміти застосовуються до автентифікації, тому запити з недійсними або
  відсутніми обліковими даними також враховуються в ліміті джерела. Точні числові
  значення лімітів налаштовує оператор, і вони можуть змінюватися; контракт
  відповіді, наведений нижче, є стабільним інтерфейсом, на який слід орієнтуватися.
</Note>

Виконуйте автентифікацію за допомогою будь-якого з двох варіантів облікових даних Basic — див.
[Quickstart](/uk/developers/v1/quickstart) (`apikey:secret` або `secret:`).
Вкажіть у `BASE` регіональний хост організації — див.
[Regions](/uk/developers/v1/regions).

## Відповідь 429

Коли ліміт вичерпано, API повертає `429 Too Many Requests` із заголовком
`Retry-After` (у секундах) і стандартним тілом problem-details:

```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`), щоб охопити колекцію меншою кількістю запитів — див.
    [pagination](/uk/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)
```

Не копіюйте цей цикл для операцій запису. Тайм-аут після запису може
означати, що сервер зафіксував зміну до розриву з’єднання. Повторюйте запис лише
тоді, коли в довідці до цієї операції прямо задокументовано ідемпотентність, зберігаючи
той самий ключ і те саме навантаження. В іншому разі перед повторною спробою звірте стан ресурсу.

## Рекомендований графік оновлення

Підбирайте періодичність оновлення з урахуванням ліміту вашого ключа та розміру сторінки. Повне
історичне завантаження великої колекції є одноразовими витратами; для
регулярних оновлень надавайте перевагу інкрементним вікнам, щоб кожен запуск залишався значно нижчим за ліміт.
Завжди явно задавайте
`limit=500` — значення за замовчуванням 25 збільшує кількість запитів.


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