Webhook — это способ сообщить другой системе: «произошло событие, пора действовать». Вместо постоянного опроса сервиса получатель заранее предоставляет адрес, на который сервис отправляет уведомление.

Целевая архитектура webhook

Webhook обычно представляет собой входящий HTTP-запрос, который сервис-источник отправляет на зарегистрированный URL при выбранном событии. Метод, формат данных, правила подписи, таймауты и повторные доставки зависят от конкретного сервиса.

sequenceDiagram
    participant A as Сервис-источник
    participant B as Точка приёма webhook
    participant Q as Очередь
    participant W as Воркер
    A->>B: POST /webhook
    B->>B: Проверка источника и данных
    B->>Q: Сохранение принятого события
    B-->>A: Успешный ответ 2xx
    Q->>W: Передача задачи
    W->>W: Идемпотентная обработка

Для фоновой обработки надёжная схема выглядит так: точка приёма (endpoint) проверяет источник и структуру запроса, сохраняет событие в устойчивой очереди, быстро возвращает успешный статус из класса 2xx, а фоновый обработчик выполняет основную работу.

Аналогия без технологий: вы не звоните курьеру каждые пять минут с вопросом «приехал?». Курьер сам сообщает, когда подъехал.

Webhook и опрос API (polling)

ПараметрОпрос API (polling)Webhook
Кто инициирует обменПолучатель регулярно обращается к сервисуСервис отправляет событие получателю
Когда появляются данныеВо время очередного запросаПосле доставки события
НагрузкаВозможны запросы без новых данныхЗапросы приходят при событиях
ЗадержкаЗависит от интервала опросаЗависит от правил доставки сервиса
ИнфраструктураМожно запускать по расписаниюОбычно нужен доступный извне HTTPS endpoint

Webhook не гарантирует мгновенную доставку. Некоторые сервисы объединяют частые изменения, доставляют события с задержкой или повторяют неудачные попытки. Например, Notion может агрегировать часть событий, а Stripe прямо предупреждает, что порядок доставки не гарантирован.

Где применяют webhook

  • Оплата: платёжный сервис сообщает об успешной операции, после чего серверная часть (backend) обновляет заказ.
  • Форма: сайт передаёт событие, а CRM создаёт лид или задачу менеджеру.
  • Notion: интеграция получает изменения доступных ей страниц и баз по выбранным типам событий.
  • Telegram: Bot API отправляет обновление на настроенный HTTPS URL.
  • GitHub: событие push передаётся на webhook, а настроенный процесс непрерывной интеграции и доставки (CI/CD) может запустить проверку, сборку или другой процесс.
💡
Webhook полезен, когда системе нужно реагировать на событие без постоянного опроса API.

Что находится в запросе

Конкретный контракт задаёт отправитель, но обычно обработчик получает несколько элементов:

  1. URL получателя — адрес точки приёма (endpoint), заранее зарегистрированный у отправителя.
  2. Метод и заголовки — часто POST, тип содержимого и данные для проверки подлинности.
  3. Тело запроса — сведения о событии. Часто используется JSON, но это не универсальное требование webhook.
  4. Идентификатор события — если сервис его предоставляет, он помогает обнаруживать повторные доставки.
  5. Версия API или схемы — определяет состав и структуру полей у некоторых сервисов.

Условный JSON-пакет может выглядеть так:

{
  "id": "evt_abc123",
  "type": "payment.succeeded",
  "data": {
    "payment_id": "pay_abc123",
    "amount": 5000,
    "currency": "RUB"
  },
  "created_at": "2026-09-08T09:00:00Z"
}

Это учебный пример, а не схема конкретного платёжного API. Названия полей нужно брать из документации выбранного сервиса.

Чеклист быстрой проверки

Точка приёма доступна по адресу и протоколу, которые поддерживает отправитель
Подписка настроена только на нужные типы событий
Подпись или другой механизм проверки источника применяется до бизнес-операций
Для проверки подписи сохраняется исходное тело запроса, если этого требует сервис
Метод, тип содержимого и схема данных валидируются
Размер запроса ограничен
Идентификаторы уже обработанных событий сохраняются
Обработка не зависит от порядка доставки
Событие надёжно сохранено до отправки успешного ответа
Долгая работа вынесена из HTTP-обработчика
Логи не содержат секретов и лишних персональных данных
Ошибки, задержки и размер очереди отслеживаются
Повторные доставки проверены в тестовой среде

Подпись и проверка источника

⚠️
Webhook приходит извне. Считайте заголовки и тело запроса недоверенными данными, пока не проверены подлинность, формат и допустимые значения.

Механизм проверки различается между сервисами. Notion использует HMAC-SHA256 в заголовке X-Notion-Signature, Stripe — заголовок Stripe-Signature и секрет, связанный с точкой приёма, а Telegram может передавать настроенный secret_token в заголовке X-Telegram-Bot-Api-Secret-Token. В Telegram это проверка секретного заголовка, а не HMAC-подпись тела.

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

Подпись сама по себе не всегда защищает от повторного воспроизведения ранее перехваченного запроса. Если протокол предоставляет подписанную метку времени, проверяйте допустимый возраст сообщения. Независимо от этого сохраняйте идентификаторы обработанных событий.

Идемпотентность, повторы и порядок событий

Отправитель может доставить одно событие несколько раз. Причиной бывает неуспешный HTTP-ответ, разрыв соединения, таймаут или ручная повторная отправка. Условия и срок повторов зависят от сервиса.

Идемпотентный обработчик не повторяет бизнес-эффект для события, которое уже успешно обработано. Незавершённое событие должно оставаться в состоянии, допускающем повторную попытку.

Практический вариант:

  1. Получить идентификатор события.
  2. Атомарно проверить и зарезервировать этот идентификатор в хранилище. Для уже завершённой записи повторный бизнес-эффект не выполняйте.
  3. Зафиксировать событие и состояние обработки.
  4. Выполнить бизнес-операцию с защитой от повторов.
  5. Отметить результат.

Не полагайтесь на хронологический порядок доставки. Stripe прямо указывает, что события могут приходить не в порядке создания. Если операция зависит от актуального состояния объекта, обработчик может получить его заново через API сервиса либо использовать собственную согласованную модель состояния.

Быстрый ответ и очередь

Успешным подтверждением доставки обычно служит статус из класса 2xx, но точные правила определяет сервис. Ответ 200 OK широко используется, а 202 Accepted по семантике HTTP означает, что запрос принят к обработке, но обработка ещё не завершена.

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

Для фоновой обработки подходят устойчивые очереди и брокеры сообщений, например Redis с подходящим механизмом очереди, RabbitMQ или BullMQ. Сама очередь не устраняет потери автоматически: нужны подтверждения, повторные попытки, контроль неуспешных задач и мониторинг.

Эталонный шаблон обработчика

получить исходные заголовки и тело
проверить допустимый метод, тип и размер запроса
проверить подпись или секрет по правилам отправителя
разобрать данные и проверить схему события
проверить идентификатор события на повтор
надёжно сохранить событие в хранилище или устойчивой очереди
вернуть предусмотренный сервисом успешный статус 2xx
в фоне выполнить идемпотентную бизнес-операцию
зафиксировать результат и метрики

Наблюдаемый признак успеха: тестовое событие отображается как успешно доставленное у отправителя, если сервис предоставляет такой журнал; событие надёжно сохраняется, а повторная доставка не создаёт второй бизнес-эффект.

Логи и мониторинг

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

  • идентификатор и тип события;
  • время получения;
  • результат проверки источника;
  • код ответа;
  • номер попытки, если он известен;
  • длительность обработки;
  • идентификатор фоновой задачи;
  • категория ошибки без секретных значений.

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

Как проверить интеграцию

  1. Используйте тестовый режим, песочницу или официальный инструмент отправителя.
  2. Отправьте одно известное событие.
  3. Убедитесь, что подпись прошла проверку и событие сохранено.
  4. Проверьте успешный HTTP-статус в журнале доставок сервиса, если такой журнал доступен.
  5. Повторите то же событие и убедитесь, что бизнес-операция не выполнилась второй раз.
  6. Если сервис или его тестовый инструмент позволяет, имитируйте временную ошибку и проверьте предусмотренное сервисом поведение повторной доставки.
  7. Если сервис или его тестовый инструмент позволяет, отправьте события в изменённом порядке и проверьте, что итоговое состояние осталось корректным.

Материал основан на официальной документации и не подтверждает результаты запуска в конкретной инфраструктуре.

Официальные источники

Актуальность изменяемого поведения проверена 8 сентября 2026 года:


Следующий шаг

Как я собрал команду из трёх ИИ-агентов и автоматизировал разработку через Notion

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

Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov