Лимиты и идемпотентность
Лимиты на ключ с заголовками X-RateLimit и Retry-After, плюс семантика Idempotency-Key: реплеи, конфликты, 24-часовое окно.
Два механизма делают интеграцию надёжной под нагрузкой и при ретраях: лимиты на ключ и идемпотентное создание инвойсов.
Лимиты
Лимиты считаются на ключ API в фиксированном 60-секундном окне:
| Scope | Эндпоинты | Live-ключ | Sandbox-ключ (pk_test_…) |
|---|---|---|---|
| Создание инвойсов | POST /v1/invoices | 30 / мин | 10 / мин |
| Чтение | GET /v1/invoices…, /v1/events, /v1/payouts | 300 / мин | 90 / мин |
Каждый авторизованный ответ несёт счётчики — гадать не приходится:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
X-RateLimit-Reset: 1694007937
X-RateLimit-Reset — Unix-timestamp конца окна. При превышении API отвечает 429 rate_limited с дополнительным заголовком Retry-After: <секунды> — дождитесь его, не крутите цикл вплотную. Если ваш чекаут легитимно требует больше, батчите создание заказов или напишите нам о повышении лимита.
Про опрос: GET /v1/invoices/{id} раз в несколько секунд на открытый чекаут — сильно ниже бюджета на чтение. Опрос обычно вообще не нужен: вебхук — основной канал; опрос — запасной.
Идемпотентное создание инвойсов
POST /v1/invoices принимает заголовок Idempotency-Key (до 120 символов). Отправляйте его при каждом создании — он превращает ретраи после сетевых таймаутов из «случайный дубль инвойса» в «тот же инвойс вернулся снова»:
- Тот же ключ + то же тело в течение 24 часов → исходный инвойс вернётся снова со статусом
201и дополнительным заголовкомIdempotent-Replay: true. Это не дубль и не ошибка. - Тот же ключ + другое тело →
409 idempotency_conflict. Ключ привязывается к точному телу запроса (канонический хеш): изменили payload — меняйте и ключ. - Ключи скоупятся на мерчанта и на режим: один и тот же ключ с
pk_test_…и позже сpk_live_…никогда не столкнутся.
curl -X POST https://api.zerokyc-payments.com/v1/invoices \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-create" \
-d '{"amount": "49.00", "order_id": "order-1042", "payment_currency": "any"}'
Хороший ключ детерминирован — стройте его из своего order id и намерения (order-1042-create), тогда ретрай после крэша или таймаута переиспользует его автоматически. Случайные ключи лишают механизм смысла.
Как это сочетается
- Создавайте с детерминированным
Idempotency-Key; и201сIdempotent-Replay, и без него — успех; сохраняйте id инвойса против своего заказа. - При
429— спатьRetry-Afterсекунд и повторить тот же запрос: идемпотентность делает это безопасным. - При
5xx/таймаутах — ретраить с экспоненциальным бэкоффом, тот же ключ, то же тело. - Исполняйте заказ по вебхуку
payment.confirmed; чтение — для сверки, а не как основной сигнал.