Rate Limits — Ограничения запросов

Документация по ограничениям запросов Trigly API: лимиты по эндпоинтам, заголовки ответов, стратегии работы с лимитами.

Обзор системы Rate Limiting

Trigly использует Redis-based систему ограничения запросов для защиты API от перегрузки и обеспечения стабильной работы всех арендаторов. Лимиты применяются на уровне middleware и различаются в зависимости от типа эндпоинта.

Все лимиты рассчитываются по скользящему окну в 60 секунд. При превышении лимита возвращается HTTP-ответ 429 Too Many Requests.


Лимиты по группам эндпоинтов

Аутентификация

Эндпоинт Лимит Окно
/api/v1/auth/* 200 запросов 60 секунд

Лимит аутентификации защищает от brute-force атак на пароли и массовой регистрации. Включает все операции: регистрация, логин, refresh token, смена пароля.

SDK (публичные эндпоинты)

Эндпоинт Лимит Окно
/api/v1/sdk/* 1000 запросов 60 секунд

Повышенный лимит для SDK-эндпоинтов, так как они принимают высокочастотный трафик с клиентских веб-сайтов: трекинг событий, push-подписки, виджеты.

Все остальные API

Эндпоинт Лимит Окно
/api/v1/* (по умолчанию) 500 запросов 60 секунд

Покрывает все остальные эндпоинты: CDP, Campaigns, Channels, Analytics, AI, Loyalty, Conversions.

Публичные эндпоинты (без лимитов middleware)

Следующие пути исключены из JWT-проверки, но подпадают под rate limiting:

  • /api/v1/auth/register — Регистрация
  • /api/v1/auth/login — Вход
  • /api/v1/auth/refresh — Обновление токенов
  • /hooks/* — Провайдерские вебхуки
  • /api/v1/campaigns/track/* — Трекинг-пиксели и ссылки
  • /api/v1/sdk/* — SDK-эндпоинты

Механизм работы

Ключ Rate Limit

Лимит считается по IP-адресу клиента. Для каждого IP и группы эндпоинтов Redis хранит счётчик с TTL, равным окну (60 секунд).

Структура ключа в Redis:

rate_limit:{prefix}:{client_ip}

Где prefix определяется по пути запроса:

  • /api/v1/auth/*auth
  • /api/v1/sdk/*sdk
  • Всё остальное → default

Алгоритм

  1. Получение IP-адреса из запроса (с учётом X-Forwarded-For за reverse proxy)
  2. Инкремент счётчика в Redis: INCR rate_limit:{prefix}:{ip}
  3. Установка TTL при первом запросе: EXPIRE rate_limit:{prefix}:{ip} 60
  4. Если значение счётчика > лимита — возврат HTTP 429

При недоступности Redis

Если Redis недоступен, rate limiting пропускается (fail-open). Это предотвращает каскадные отказы: лучше временно снять ограничения, чем заблокировать весь API.


HTTP-ответ при превышении лимита

При превышении rate limit Trigly возвращает:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30

{
  "detail": "Rate limit exceeded. Please retry after 30 seconds."
}

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

Заголовок Описание
Retry-After Рекомендуемое время ожидания (в секундах)

Лимиты каналов доставки

Помимо HTTP rate limits, каждый канальный адаптер имеет внутренние ограничения скорости отправки:

Канал Провайдер Лимит Механизм
Email SMTP Без ограничений
Email Unisender 50 сообщений/сек asyncio.sleep delay
Telegram Bot API 30 сообщений/сек asyncio.sleep delay
SMS SMS.ru 100 сообщений/сек asyncio.sleep delay
WhatsApp Cloud API 80 сообщений/сек asyncio.sleep delay
Push VAPID 100 сообщений/сек asyncio.sleep delay

Эти лимиты реализованы в BaseChannelAdapter._check_rate_limit() через delay-based throttling. При пакетной отправке (send_batch) задержка вставляется между сообщениями.


Frequency Capping (ограничение частоты для контактов)

Отдельно от API rate limits существует система ограничения частоты сообщений для конечных получателей — Frequency Capping. Она предотвращает «заспамливание» контакта при запуске нескольких кампаний одновременно.

Уровни ограничений

Уровень По умолчанию Описание
Дневной 3 сообщения Максимум сообщений одному контакту в день
Недельный 10 сообщений Максимум в неделю
Месячный 30 сообщений Максимум в месяц

Тихие часы (Quiet Hours)

Система не отправляет сообщения в ночное время (по умолчанию 22:00 — 08:00 по локальному времени контакта). Сообщения откладываются до начала рабочих часов.

Хранение

Счётчики frequency capping хранятся в Redis:

freq:{org_id}:{customer_id}:daily:{date}
freq:{org_id}:{customer_id}:weekly:{week}
freq:{org_id}:{customer_id}:monthly:{month}

При выполнении кампании (execute_campaign) перед отправкой каждого сообщения вызывается FrequencyService.check_frequency(). Если лимит превышен — сообщение пропускается и контакт помечается как suppressed.


Лимиты организации

Бюджетные лимиты

Каждый канал имеет настраиваемые лимиты:

Параметр Описание
daily_limit Максимум сообщений в день через канал
monthly_limit Максимум сообщений в месяц
monthly_budget Максимальный бюджет в рублях в месяц

При достижении бюджетного лимита:

  • 80% — генерируется предупреждение
  • 100% — канал блокируется, BudgetService переключает на бесплатную альтернативу

Лимиты импорта

Операция Лимит
CSV-импорт контактов 100 000 строк за один файл
Пакетный трекинг событий 1000 событий в одном batch-запросе
Bulk-операции (update/delete/tag) 10 000 контактов за операцию

Стратегии работы с лимитами

Для SDK-интеграций

  1. Батчирование: Группируйте события и отправляйте через /api/v1/sdk/batch вместо одиночных вызовов /api/v1/sdk/track.
  2. Буферизация на клиенте: Накапливайте 10 событий или ждите 5 секунд, затем отправляйте пакетом.
  3. Retry с backoff: При получении HTTP 429 ждите Retry-After секунд перед повтором.
async function trackWithRetry(event, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch('/api/v1/sdk/track', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': apiKey
      },
      body: JSON.stringify(event)
    });

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '30');
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      continue;
    }

    return response;
  }
  throw new Error('Rate limit exceeded after retries');
}

Для API-интеграций

  1. Кэширование: Кэшируйте ответы GET-запросов на стороне клиента (список контактов, сегменты, шаблоны).
  2. Пагинация: Используйте разумный per_page (20-50), не запрашивайте все данные сразу.
  3. Webhook вместо polling: Подпишитесь на вебхуки вместо периодического опроса статусов кампаний.
  4. Параллелизм: Ограничивайте количество одновременных запросов до 10-20.

Для массовых операций

  1. Bulk API: Используйте bulk-эндпоинты (/api/v1/cdp/contacts/bulk/*) вместо поштучных запросов.
  2. CSV-импорт: Для загрузки больших объёмов контактов используйте /api/v1/cdp/imports — асинхронная обработка через Celery.
  3. Экспорт: Используйте /api/v1/cdp/exports — асинхронная генерация файла, скачивание по готовности.

Мониторинг и диагностика

Как узнать текущее потребление

На данный момент Trigly не предоставляет эндпоинт для проверки текущего состояния rate limit. Рекомендуется:

  1. Логировать все HTTP 429 ответы на стороне клиента
  2. Отслеживать среднее количество запросов в минуту в вашем приложении
  3. Настроить алерты при превышении 80% от лимита

Типичные проблемы

Проблема: Массовый 429 при импорте контактов. Решение: Используйте CSV-импорт через /api/v1/cdp/imports вместо поштучного создания через POST.

Проблема: 429 при трекинге событий на высоконагруженном сайте. Решение: Буферизация + batch-отправка. 1000 запросов/мин для SDK достаточно для ~16 событий/секунду.

Проблема: 429 при работе с кампаниями. Решение: 500 запросов/мин — это ~8 запросов/секунду. Если вы управляете сотнями кампаний программно, добавьте задержку между запросами.


Сравнение с конкурентами

Платформа Стандартный лимит SDK-лимит
Trigly 500/мин 1000/мин
Mindbox 300/мин 600/мин
Unisender 100/мин
SendPulse 10/сек (600/мин) Не применимо

Trigly предоставляет конкурентоспособные лимиты, достаточные для большинства сценариев использования, включая высоконагруженные e-commerce сайты.

Не нашли ответ?

Swagger UI с интерактивной документацией и поддержка в Telegram.