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

# Ограничения частоты запросов

> Лимиты запросов для Public API Living Security, контракт ответа 429 и порядок повторных попыток с использованием Retry-After.

API `/v1` применяет два независимых лимита запросов. Запрос отклоняется,
если исчерпан любой из них.

| Лимит | Область применения |
| - | - |
| На ключ API | Каждый запрос, использующий этот ключ, с любого адреса |
| На IP-адрес клиента | Каждый запрос с этого адреса, аутентифицированный или нет |

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

<Note>
  Ограничения применяются до аутентификации, поэтому запросы с недействительными
  или отсутствующими учётными данными также учитываются в лимите источника.
  Точные числовые значения лимитов настраиваются оператором и могут изменяться;
  контракт ответа, описанный ниже, является стабильным интерфейсом, на который
  следует ориентироваться при разработке.
</Note>

Используйте для аутентификации любую из двух форм учётных данных Basic — см.
[Краткое руководство](/ru/developers/v1/quickstart) (`apikey:secret` или `secret:`).
Укажите в `BASE` региональный хост организации — см.
[Регионы](/ru/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`), чтобы охватить коллекцию
    меньшим числом запросов — см. [постраничную навигацию](/ru/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.