Перейти к содержанию
Версия контракта: 0.3.3 — спека

Лимиты и квоты

Страница для интегратора: какие границы есть у хаба, что происходит при их достижении и как узнать свои значения.

Все действующие для вас значения отдаёт GET /v1/account — там же, где хаб их и применяет. Числа ниже — умолчания; ваши могут отличаться, и правда в ответе ручки, а не на этой странице.

Темп запросов

Каждый ключ ограничен по числу запросов в секунду — limits.api_rps из GET /v1/account; у каждого ключа аккаунта свой счётчик. Превышение — 429 rate_limited с Retry-After. Заголовки X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset приходят и на успешном ответе, и на отказе — кроме двух случаев: запрос отвергнут ещё до проверки темпа (например, 401), или счётчик темпа временно недоступен и решение принято без него. Тогда заголовков нет вовсе: остаток, посчитанный без счётчика, был бы выдумкой. Отсутствие заголовка не означает «лимита нет».

Повторять следует не раньше retry_after и с тем же Idempotency-Key: отказ по темпу к ключу не приколачивается.

Анти-флуд по получателю

Защита абонента, а не защита от вас: три окна считаются независимо, и в отказе называется то, которое сработало первым.

Окно Умолчание Что означает
пауза 60 с минимальный интервал между сообщениями одному номеру
час 5 сколько сообщений на номер за час
сутки 20 сколько сообщений на номер за сутки

Отказ — 422 recipient_flood_limited, а не 429: проблема не в темпе клиента.

Окна общие для всех классов. Счётчик ведётся на номер получателя в вашем аккаунте и режиме, класс сообщения в нём не участвует: сервисное сообщение и одноразовый код тратят одни и те же окна. Сервисное сообщение, отправленное абоненту за минуту до того, как он запросил код, задержит код на паузу. Планируйте рассылки с учётом этого — или договоритесь о своих значениях окон.

В песочнице (test-ключ) анти-флуд действует только на магический номер +79000000004 — на нём он и показывается (вторая отправка за 5 минут — 422 recipient_flood_limited). Остальные номера песочницы окон не тратят, чтобы повторный прогон сценария не упирался в отказ.

Повтор с уже использованным client_ref окна не тратит: он не создаёт сообщения.

Если счётчик отправок временно недоступен, одноразовые коды проходят, а всё остальное получает тот же 422 recipient_flood_limited — но без retry_after: сколько осталось до конца окна, знает счётчик, а его в этот момент нет, и выдуманная пауза хуже отсутствующей. Асимметрия намеренная. Код приходит в ответ на действие человека, который прямо сейчас ждёт его, чтобы войти, и несколько лишних сообщений стоят дешевле сломанного входа. Рассылка, отправленная без счётчика, придёт абоненту несколькими экземплярами — и узнаем мы об этом от него.

Размер пакета

До 1000 сообщений в POST /v1/messages/batch; для вашего аккаунта предел может быть меньше — limits.batch_max в GET /v1/account. Больше — 422 batch_too_large, пустой пакет — 422 invalid_parameter. Пакет не «отправляется целиком или никак»: каждый элемент получает свой результат, а отказ одного не отменяет остальные.

Предел расхода

Граница вида «этому проекту можно тратить столько-то за период»; ставится оператором хаба по договорённости. Это не купленный объём: хаб внутренний и ничего не продаёт.

  • при пересечении мягкого порога приходит событие account.spend_threshold — один раз за период, а не на каждое сообщение;
  • при достижении предела приём отвечает 422 spend_limit_reached. Повтор не поможет: границу двигает человек.

Текущее состояние — в GET /v1/account (spend_limit: предел, потрачено, период, порог). В песочнице предела нет: тестовые сообщения ничего не стоят.

Суточный предел хаба

Общий на весь хаб, ниже операторского: упереться в свой безопаснее, чем в чужой, потому что свой мы видим заранее.

При достижении приём отвечает 429 hub_daily_limit_reached с retry_after до полуночи UTC (не меньше минуты). Одноразовые коды не исключение: канал остановлен целиком, и принятый код всё равно не ушёл бы — отказ на приёме даёт возможность доставить его другим способом. Отказ получают и test-ключи: признак общий для хаба, режим ключа не проверяется. Пакет проверяется один раз, до создания, — целиком.

Если признак остановки временно не читается, приём не останавливается: недоступность служебного хранилища не должна становиться недоступностью хаба, и сообщение принимается как обычно.

Неудачные попытки входа

Считаются отдельно, по адресу клиента: больше 20 неудачных входов за минуту (скользящее окно, успешные запросы счётчик не сбрасывают) — и вход отвечает 429 rate_limited («Слишком много неудачных попыток входа») с retry_after, не доходя до проверки ключа. Запросы без заголовка ключа не считаются. Обычной интеграции это не касается — ключ у вас один и он верный; гейт стоит против перебора. Типичная ловушка — ротация ключа, после которой часть процессов ещё ходит со старым: их отказы запрут вход и новому ключу с того же адреса.

Что делать при отказе

Код Повторять С тем же Idempotency-Key
429 rate_limited после retry_after да
429 hub_daily_limit_reached после retry_after да
422 recipient_flood_limited не раньше конца окна нет, с новым
422 spend_limit_reached нет, пока границу не подняли —
422 batch_too_large нет, разбейте пакет —