Для разработчиков

Лимиты

Мы следим за стабильностью API, поэтому есть лимиты на запросы (rate limiting). Они гибкие, зависят от нагрузки, но мы сделали их комфортными — должно хватить для любых ваших задач.

Входящие вебхуки

Входящие вебхуки
Лимит привязан к идентификатору вебхука в пути.
Например, для /webhooks/user123 считаем по user123
Лимит
~10 запросов
Период
1 секунда

Если за секунду отправите больше указанного количества запросов на один идентификатор, лишние получат 429 Too Many Requests. В заголовке Retry-After мы укажем, через сколько секунд можно попробовать снова.

API

Отправка, изменение и удаление сообщений
Считаем по токену авторизации (заголовок HTTP_AUTHORIZATION). Один токен — один лимит. Запросы учитываются по каждому чату отдельно. Дополнительно действует общий предел по всем чатам сразу — 30 запросов за 5 секунд: он допускает короткие ускорения выше посекундного лимита, но не даёт держать такой темп долго.
Лимит
~4 запроса
Период
1 секунда
Сущность
chat_id
Получение сообщений
Считаем по токену авторизации (заголовок HTTP_AUTHORIZATION). Один токен — один лимит.
Лимит
~10 запросов
Период
1 секунда
Остальные методы API
Считаем по токену авторизации (заголовок HTTP_AUTHORIZATION). Один токен — один лимит.
Лимит
~50 запросов
Период
1 секунда
Чтение истории событий бота
Действует на GET /webhooks/events. Считаем по токену авторизации.
Лимит
~5 запросов
Период
2 секунды
Инвентаризация пространства
Действует на GET /company/chats и GET /company/bots. Считаем по токену авторизации. Лимит заметно строже общего: при странице в 50 записей за минуту получится обойти около 1500 чатов или ботов.
Лимит
~30 запросов
Период
1 минута
Список чатов с постраничной пагинацией
Действует на GET /chats, когда выборка запрошена номером страницы, а не курсором. Считаем по токену авторизации. Запрос с cursor или limit под этот лимит не подпадает и работает в рамках общего.
Лимит
~10 запросов
Период
1 секунда
Сообщения в один чат за сутки
Действует на POST /messages. Считаем по паре «отправитель и чат» за последние 24 часа. Сообщения в тред засчитываются в чат, которому принадлежит родительское сообщение. Квоту расходуют только созданные сообщения: запрос, отклонённый проверкой, её не тратит.
Лимит
5 000 сообщений
Период
Скользящие 24 часа
Сущность
chat_id

Если за секунду будет больше указанных запросов с одним токеном, API вернёт 429 Too Many Requests. В заголовке Retry-After мы укажем, через сколько секунд можно попробовать снова. Тело такого ответа — короткий текст с Content-Type: text/plain, а не JSON: лимиты на частоту запросов обрабатываются до того, как запрос доходит до метода.

Превышение суточного предела отвечает так же — 429 с кодом rate_limit в errors[].code и заголовком Retry-After. Отправка в этот чат приостанавливается на час, и каждая следующая попытка во время паузы удваивает её: 1, 2, 4, 8, 16 и до 24 часов. Дождитесь срока из Retry-After — он учитывает и паузу, и момент, когда в окне освободится место. Отправка, прошедшая после паузы, возвращает шкалу к началу.

  • Лимиты гибкие: они ориентировочные и могут меняться, чтобы всё работало гладко;
  • Должно хватать на всё: мы настроили их так, чтобы вам было комфортно в любых сценариях;
  • Если упёрлись в лимит: при ошибке 429 смотрите заголовок Retry-After — он подскажет, через сколько секунд повторить запрос (или используйте экспоненциальный backoff, если хотите перестраховаться).

Защита от перегрузки

Если приложение продолжает слать запросы выше лимитов даже после 429, доступ токена может быть временно ограничен — это защита от сбойных циклов и случайной перегрузки. Чтобы этого избежать:

  • Соблюдайте Retry-After — он указывает, через сколько секунд имеет смысл повторить
  • Используйте экспоненциальный backoff с jitter — готовые примеры ниже в разделе Повторные запросы
  • Если ваш сервис не успевает обрабатывать ответы, приостановите запросы, а не ускоряйте retry

Повторные запросы (Retry)

SDK (TypeScript, Python) уже включают автоматический retry с экспоненциальным backoff. Ниже — реализация для кастомных HTTP-клиентов.

TypeScript

async function withRetry<T>(  fn: () => Promise<T>,  maxRetries = 3): Promise<T> {  for (let attempt = 0; attempt <= maxRetries; attempt++) {    try {      return await fn()    } catch (error: any) {      // 429 Too Many Requests — ждём Retry-After или backoff      if (error.status === 429) {        const retryAfter = error.headers?.["retry-after"]        const delay = retryAfter          ? parseInt(retryAfter) * 1000          : Math.pow(2, attempt) * 1000 * (0.5 + Math.random())        await new Promise(r => setTimeout(r, delay))        continue      }      // 5xx — серверная ошибка, backoff с jitter      if (error.status >= 500 && attempt < maxRetries) {        const delay = Math.pow(2, attempt) * 1000 * (0.5 + Math.random())        await new Promise(r => setTimeout(r, delay))        continue      }      // 4xx (кроме 429) — не повторяем      throw error    }  }  throw new Error("Max retries exceeded")} // Использованиеconst users = await withRetry(() => client.users.listUsers())

Python

import time, random async def with_retry(fn, max_retries=3):    for attempt in range(max_retries + 1):        try:            return await fn()        except Exception as e:            status = getattr(e, "status_code", getattr(e, "status", 0))            headers = getattr(e, "headers", {})            # 429 Too Many Requests            if status == 429:                retry_after = headers.get("Retry-After")                delay = int(retry_after) if retry_after else (2 ** attempt) * (0.5 + random.random())                time.sleep(delay)                continue            # 5xx — серверная ошибка            if status >= 500 and attempt < max_retries:                time.sleep((2 ** attempt) * (0.5 + random.random()))                continue            raise    raise Exception("Max retries exceeded") # Использованиеusers = await with_retry(lambda: client.users.list_users())

Стратегия повторов

КодДействиеЗадержка
429ПовторитьRetry-After header или exponential backoff: 1с, 2с, 4с × jitter
500, 502, 503, 504ПовторитьExponential backoff с jitter: ~1с, ~2с, ~4с
400, 401, 403, 404, 422Не повторятьОшибка клиента — нужно исправить запрос
Максимум 3 повтора на каждый запрос. Jitter (случайный множитель 0.5–1.5) предотвращает «thundering herd» при массовых 429.