Лимиты и квоты¶
Страница для интегратора: какие границы есть у хаба, что происходит при их достижении и как узнать свои значения.
Все действующие для вас значения отдаёт 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 |
нет, разбейте пакет | — |