Представьте курьера, который вместо серии звонков «приехал? приехал?» сам пишет сообщение в момент прибытия. Webhook устроен похожим образом: одна система не опрашивает другую с вопросом «есть новости?», а молча ждёт, пока вторая сама отправит сигнал. Этот сигнал — обычный HTTP-запрос с данными события.
Модель «запрос-ответ», к которой привыкли разработчики, предполагает инициативу на стороне клиента: вы спрашиваете — сервер отвечает. Webhook переворачивает направление: теперь сервер сам стучится к вам, когда произошло что-то важное. Это меняет архитектуру, требования к безопасности и способ обработки нагрузки.
Для команд, которые работают с платежами, формами, чат-ботами или CI/CD, webhook — не экзотика, а базовый строительный блок. Без него не получится построить мгновенную реакцию на событие: придётся опрашивать API по расписанию и мириться с задержками.
Что это
Webhook — это HTTP-запрос, который один сервис отправляет другому в момент наступления события. Получатель заранее регистрирует свой URL в настройках сервиса-источника, а отправитель вызывает этот URL при каждом событии. Технически это обычный POST-запрос с телом в формате JSON.
Ключевое отличие от привычного API-вызова — кто инициирует обмен. При обычном запросе вы сами обращаетесь к сервису: «дай данные». При webhook сервис обращается к вам: «произошло вот что». Вы не спрашиваете — вам сообщают.
Зачем нужно
Там, где важна скорость реакции, webhook даёт почти мгновенное уведомление вместо цикла опроса. Несколько типовых сценариев:
- Платежи. Клиент оплачивает заказ. Платёжный сервис (YooKassa, Stripe, Тинькофф) отправляет webhook на backend. Backend обновляет статус заказа и формирует чек.
- Формы. Человек заполнил форму на сайте. Сайт отправляет событие. CRM создаёт лид и уведомляет менеджера.
- Notion. В базе данных появилась новая страница. Webhook уходит на backend, и агент запускает обработку.
- Telegram. Пользователь написал боту. Telegram отправляет webhook, бот обрабатывает сообщение и отвечает.
- GitHub. В репозиторий пришёл новый commit. GitHub отправляет webhook, CI/CD запускает сборку и тесты.
Во всех случаях webhook особенно полезен, когда нужна быстрая реакция: обработка оплаты, отправка уведомления, запуск агента, обновление статуса.
Как устроено
Webhook — это HTTP POST-запрос с данными в JSON. Три ключевых компонента:
- URL получателя — адрес, куда сервис-отправитель направит запрос. Вы регистрируете его заранее в настройках сервиса.
- Заголовки (headers) — содержат метаданные запроса, включая подпись для проверки подлинности.
- Тело запроса (body) — JSON с данными события: тип, идентификаторы, метаданные.
{
"event": "payment.succeeded",
"payment_id": "pay_abc123",
"amount": 5000,
"currency": "RUB",
"timestamp": "2026-05-11T12:00:00Z"
}
Схема взаимодействия
sequenceDiagram
participant A as Сервис-источник
participant B as Ваш backend
Note over A,B: Регистрация webhook URL
A->>B: POST /webhook (событие: оплата прошла)
B->>B: Проверка подписи
B->>B: Обработка данных
B-->>A: 200 OK
Получатель проверяет подпись, обрабатывает данные и возвращает 200 OK. Отправитель ждёт ответ ограниченное время — если ответа нет, он повторяет запрос.
Webhook vs опрос (polling)
| Параметр | Обычный API-запрос (polling) | Webhook |
|---|---|---|
| Кто инициирует | Вы спрашиваете сервис | Сервис сам сообщает вам |
| Когда срабатывает | По расписанию или по запросу | В момент события |
| Нагрузка | Много пустых запросов | Только когда есть данные |
| Задержка | Зависит от частоты опроса | Почти мгновенно |
| Сложность | Проще настроить | Нужен публичный URL для приёма |
Опрос проще настроить — не нужен публичный endpoint, не нужна обработка входящих запросов. Но он создаёт лишнюю нагрузку и добавляет задержку: чем реже опрашиваете, тем дольше ждёте. Webhook устраняет обе проблемы, но требует публичного URL и осторожной обработки входящих данных.
Когда использовать
Webhook подходит, когда событие происходит на стороне другого сервиса, а вам нужно реагировать быстро. Конкретные сценарии:
- Обработка платёжных уведомлений в реальном времени.
- Автоматический запуск процессов при изменении данных (новая страница в Notion, новый commit в GitHub).
- Чат-боты, где ответ должен приходить мгновенно после сообщения пользователя.
- Интеграции с CRM, когда лид создаётся в момент отправки формы.
Webhook не подходит, когда вам нужен большой объём данных по запросу, когда событие не определено на стороне отправителя, или когда нет возможности выставить публичный endpoint для приёма.
Webhook и очереди
Webhook сообщает о событии, но тяжёлую обработку не стоит делать прямо в обработчике. Правильная схема:
- Принять webhook, ответить 200 OK.
- Положить данные в очередь (Redis, RabbitMQ, BullMQ).
- Фоновый воркер достаёт задачу и обрабатывает.
Так webhook не блокируется, обработка не теряется при ошибке, а повторные попытки работают корректно.
Пример
Платёжный сервис отправляет webhook на ваш endpoint /webhook. Запрос содержит данные об успешной оплате. Обработчик принимает запрос, проверяет подпись, отвечает 200 OK и кладёт задачу в очередь. Фоновый воркер обновляет заказ в базе и отправляет чек клиенту.
{
"event": "payment.succeeded",
"payment_id": "pay_abc123",
"amount": 5000,
"currency": "RUB",
"timestamp": "2026-05-11T12:00:00Z"
}
Сервис-отправитель ждёт ответ ограниченное время — обычно от 5 до 30 секунд. Если обработка дольше, ответ нужно отправить сразу, а данные поставить в очередь.
Ограничения
Ограничения
Webhook — это входящий запрос извне. К нему нужно относиться как к непроверенным данным: всегда проверять подпись, валидировать содержимое и логировать запросы.
Повторные доставки — одно и то же событие может прийти дважды.
Отправитель повторяет запрос, если не получил 200 OK. Backend должен обрабатывать повторные события без побочных эффектов (идемпотентность).
Ограниченное время ожидания — отправитель ждёт ответ 5-30 секунд.
Если обработка дольше, ответ нужно отправить сразу, а данные поставить в очередь.
Нужен публичный URL — endpoint должен быть доступен из интернета.
Это требует защиты от DDoS, спама и несанкционированных запросов.
Хранение секретного ключа — ключ для проверки подписи должен храниться безопасно, не в коде.
Переменные окружения или менеджер секретов.
Антипаттерны
Антипаттерны
Каждая из этих ошибок может привести к потере данных, дубликатам операций или компрометации endpoint.
Не проверять подпись
— без проверки злоумышленник может подделать запрос и отправить произвольные данные на ваш endpoint.
Тяжёлая обработка в обработчике — если обработка занимает больше таймаута отправителя, запрос будет повторен, и вы получите дубликат.
Выносите в очередь.
Не логировать входящие запросы
— без логов невозможно отладить, что пришло, когда пришло и почему обработка сломалась.
Игнорировать идемпотентность
— повторный запрос не должен создавать второй заказ, второй платёж или вторую запись в базе.
Хранить секретный ключ в коде
— ключ в репозитории — это утечка, которая позволяет любому подделать webhook.
Чеклист
Чеклист
Перед запуском webhook-обработчика в продакшен проверьте каждый пункт.
URL webhook доступен извне
— публичный endpoint работает и принимает POST.
Подпись проверяется перед обработкой
— секретный ключ используется для верификации каждого запроса.
Входящие данные валидируются
— формат, типы, обязательные поля проверяются до обработки.
Обработка идемпотентна
— повторный запрос не ломает систему и не создаёт дубликатов.
Тяжёлая обработка в очереди
— webhook отвечает 200 OK быстро, обработка идёт в фоновом воркере.
Ответ 200 OK отправляется быстро
— до истечения таймаута отправителя.
Логирование входящих запросов
— каждый запрос записывается для отладки.
Мониторинг и алерты
— при ошибках обработки срабатывает уведомление.
Секретный ключ хранится безопасно
— в переменной окружения или менеджере секретов, не в коде.
Endpoint защищён от DDoS
— rate limiting, WAF или другой механизм защиты активен.
Ссылки
Ссылки
- Документация: Stripe Webhooks
- Документация: GitHub Webhooks
- Документация: Telegram Bot API Webhooks
- Стандарт: HTTP POST — MDN
- Документация: YooKassa API Webhooks