ДокументацияВведение
Коды ошибок

Интеграция

Лимиты запросов

Rate limits, заголовки, retry

PayBot ограничивает частоту запросов: базовый лимит API — 20 запросов в минуту на ключ. При превышении приходит 429 с кодом rate_limit_exceeded. Читайте заголовки X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset, чтобы притормаживать заранее, а на 429 — повторять запрос с экспоненциальным backoff, ориентируясь на X-RateLimit-Reset.

Лимиты не действуют для тарифа enterprise и для ключей в тестовом режиме (kp_test_...) — там частота не ограничивается.

Какие лимиты действуют

ЛимитЗначение
API (общий)20 запросов/мин на ключ
Аутентификация (/auth/*)10 запросов/мин
Checkout — данные ссылки60/мин на токен+IP
Checkout — статус (поллинг)120/мин (не чаще ~1 раза в 500 мс)
Checkout — обновление QR10/мин (только при истёкшем qr_expires_at)
Checkout — email плательщика20/мин
Платежи в месяцtrial 30 / starter 200 / professional 1500 / enterprise 999999

Помимо частотного лимита есть месячный лимит числа платежей по тарифу. Его превышение — это не rate_limit_exceeded, а отдельный код plan_limit_exceeded (тоже 429), который стоит показывать как апселл, а не как ошибку. О различии кодов — в разделе коды ошибок.

Заголовки ответа

На каждый ответ API проставляет три заголовка (они проброшены в CORS-expose, поэтому доступны из браузера).

ЗаголовокЗначение
X-RateLimit-Limitсколько запросов в окне разрешено
X-RateLimit-Remainingсколько запросов осталось в текущем окне
X-RateLimit-Resetкогда окно сбросится (используйте для backoff)

Читайте X-RateLimit-Remaining после каждого ответа: если он близок к нулю, притормозите отправку заранее, не доводя до 429.

Что делать при ошибке 429

429 означает, что вы превысили лимит. Не ретрайте немедленно в цикле — это только продлевает блокировку. Подождите до момента из X-RateLimit-Reset и повторяйте с экспоненциальным backoff (задержка удваивается с каждой попыткой) плюс небольшой случайный джиттер, чтобы параллельные клиенты не били синхронно.

python
Скачать
import time
import random
import requests

def request_with_backoff(method: str, url: str, max_retries: int = 5, **kwargs):
    delay = 1.0
    for attempt in range(max_retries):
        resp = requests.request(method, url, **kwargs)
        if resp.status_code != 429:
            return resp
        reset = resp.headers.get("X-RateLimit-Reset")
        try:
            wait = max(float(reset) - time.time(), 0) if reset else delay
        except ValueError:
            wait = delay
        time.sleep(wait + random.uniform(0, 0.5))  # джиттер против синхронных ретраев
        delay *= 2
    return resp

resp = request_with_backoff(
    "GET",
    "https://api.paybot.kz/v2/payments",
    headers={"X-API-Key": "kp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
)

Для идемпотентных POST (создание QR, счёта, возврата) повторяйте запрос с тем же Idempotency-Key, чтобы ретрай после 429 не создал дубликат операции — см. идемпотентность.

Исключения из лимитов

Частотный лимит не применяется в двух случаях:

  • Тариф enterprise — запросы не ограничиваются по частоте.
  • Тестовый режим ключа (kp_test_...) — обходятся и rate-limit, и проверка живости сессии Kaspi, работает sandbox.

Это удобно для нагрузочной отладки: гоняйте интеграцию на тестовом ключе без риска упереться в лимит, а на боевом закладывайте backoff. Подробнее про тестовый режим — в разделе тестирование.

FAQ

Как понять, что я близок к лимиту, до 429?

Смотрите X-RateLimit-Remaining в каждом ответе. Когда остаток мал, замедлите отправку сами — это надёжнее, чем ловить 429 и откатываться.

Чем rate_limit_exceeded отличается от plan_limit_exceeded?

rate_limit_exceeded — вы шлёте слишком часто (частотный лимит, ~20/мин), лечится backoff. plan_limit_exceeded — исчерпан месячный лимит платежей по тарифу, backoff не поможет: нужен апгрейд плана, поэтому показывайте апселл.

Poll-ить статус checkout можно как часто?

До 120 запросов в минуту на токен, то есть не чаще примерно раза в 500 мс. QR обновляйте (refresh-qr) только по факту истечения qr_expires_at — там лимит жёстче, 10/мин.

Считается ли в лимит платежей неоплаченный QR?

Месячный лимит тарифа считает оплаченные платежи. Частотный же лимит (20/мин) считает сами HTTP-запросы независимо от исхода.

Смежные разделы