Webhook vs Callback. Различия и почему их путают
Каждый раз, когда я объясняю тему асинхронных интеграций, у слушателей возникает один и тот же вопрос: «А в чём разница между webhook и callback, разве это не одно и то же?». Давайте разбираться.
Короткий ответ
Callback — это общий термин в программировании, обозначающий паттерн «вызову тебя позже». В роли callback может выступать функция (переданная как аргумент) или URL‑адрес, который будет вызван после завершения некоторой операции. Важно: callback бывает синхронным (например, функция обратного вызова в Array.map вызывается сразу) и асинхронным (когда вызов откладывается до окончания длительной задачи). В контексте интеграций и API мы говорим именно об асинхронном callback, обычно реализованном через HTTP‑запрос на указанный URL.
Webhook — это частный случай асинхронного callback, но реализованный через HTTP между двумя независимыми системами. Сервис заранее регистрирует URL, и сторонний сервис сам, по своей инициативе, присылает туда POST‑запрос при наступлении события. Простыми словами, webhook — это HTTP‑callback между сервисами, а не любой callback вообще.
Оба механизма решают одну задачу — «сообщить о результате позже, не блокируя вызывающего», — но у них разная область применения, разный жизненный цикл и разный уровень связности.
Откуда путаница
Путаница возникает из‑за того, что webhook часто называют «callback URL», и оба используют похожий синтаксис (передача URL). Однако их назначение и способ настройки кардинально отличаются. Ниже таблица, которая поможет разобраться.
| Критерий | Callback | Webhook |
|---|---|---|
| Уровень | Внутри кода / внутри кода приложения | Между независимыми системами по HTTP |
| Что передается | Функция или URL, привязанный к конкретному запросу | Заранее зарегистрированный URL, привязанный к событию/подписке |
| Кто инициирует повторный вызов | Тот же процесс/API, что обрабатывал исходный запрос | Внешняя система, независимо от того, кто и когда ее “спросил” |
| Количество срабатываний | Обычно один раз, на конкретный запрос | Многократно, каждый раз при событии, пока подписка активна |
| Настройка | Указывается при каждом вызове API (в теле запроса) | Настраивается один раз при интеграции (подписка на событие) |
| Язык/платформа | Часто завязан на конкретный язык и окружение (например, функция в коде) | Языко-независим — просто HTTP-запрос |
| Пример | POST /transfer с полем callbackUrl, куда придет статус перевода | Подписка на событие invoice.paid от YooKassa — уведомления приходят сами |
Обратите внимание: в строке «Количество срабатываний» речь идет именно об асинхронных callback‑URL, передаваемых в запросе. Обычные callback‑функции в коде могут вызываться многократно (например, обработчик кликов) — важно не путать эти понятия.
Webhook как один из способов асинхронного взаимодействия
Webhook — это не единственный способ организовать асинхронную связь между сервисами. Вместе с ним используются:
- Polling (клиент периодически опрашивает сервер на предмет готовности результата)
- Long‑polling (клиент открывает запрос и ждёт, пока сервер ответит, когда появится событие)
- WebSockets (постоянное двунаправленное соединение)
- Message queues (брокеры сообщений, например, RabbitMQ или Kafka)
Webhook хорош тем, что он push‑ориентирован — сервис сам отправляет данные, когда они готовы, и не требует постоянного соединения. Это экономит ресурсы и упрощает архитектуру, особенно при интеграции с внешними провайдерами.
Аналогия для понимания
Callback — это когда вы заводите тикет в поддержку, оставляете номер телефона, и вам звонят один раз, когда очередь подошла. Webhook — это как установленный на двери звонок, срабатывает каждый раз, когда кто-то приходит, независимо от того, ждете вы гостя или нет.
Еще пример: пользователь нажал «Оплатить» и вы передали callbackUrl конкретно для этой транзакции — это callback, привязанный к одному действию. А если вы один раз настроили у платежного провайдера подписку «присылай мне уведомление на этот URL каждый раз, когда на мой счет приходит платеж» — это webhook, который будет работать постоянно, без повторной настройки.
Схема: Callback (в рамках одного запроса)
Callback-URL привязан к конкретному вызову API и срабатывает один раз, когда операция завершена.

Схема: Webhook (подписка на события)
Webhook настраивается один раз (подписка), а срабатывает многократно — каждый раз, когда происходит событие, даже если приложение ничего не запрашивало.

Схема: как они соотносятся друг с другом
Webhook — это подмножество callback: любой webhook является callback-механизмом, но не любой callback — webhook.

Практический пример кода
Callback URL (разовый запрос)
POST /api/v1/transfer
{
"amount": 100,
"accountTo": "40817...",
"callbackUrl": "https://bv-dev.ru/ft-callback"
}
Регистрация webhook (подписка, делается один раз)
POST /api/v1/webhooks
{
"url": "https://bv-dev.ru/webhooks/payments",
"events": ["payment.succeeded", "payment.failed"]
}
Ключевое отличие: в первом случае URL передаётся вместе с каждым запросом, во втором — URL регистрируется один раз, а данные будут приходить по мере возникновения событий, без привязки к конкретному запросу.
Другие популярные сценарии использования webhook
- GitHub – уведомления о push, создании pull request, комментариях, релизах
- Stripe / PayPal / YooKassa – уведомления о платежах, возвратах, подписках
- CRM-системы – обновление контактов, сделок, задач
- CI/CD (Jenkins, GitLab) – запуск сборки после коммита, уведомление о результате
- Мониторинг (Prometheus Alertmanager) – отправка алертов в вашу систему
Безопасность и надежность: о чем нельзя забывать
При работе с webhook‑ами в продакшене недостаточно просто принять запрос. Нужно позаботиться о следующих аспектах:
- Проверка подлинности – как убедиться, что запрос пришёл именно от провайдера, а не от злоумышленника? Обычно используется подпись (HMAC с секретным ключом, JWT) или проверка IP‑адресов (но IP можно подделать). Всегда проверяйте подпись в заголовках (например,
X‑Signature). - Идемпотентность – провайдер может дублировать одно и то же событие (например, из‑за сетевых ошибок). Ваш обработчик должен быть идемпотентным: повторная обработка того же события не должна приводить к нежелательным побочным эффектам. Используйте уникальный
eventIdи храните его в БД, чтобы отсеивать дубли. - Повторные попытки (retries) – если ваш endpoint вернул ошибку (4xx или 5xx), провайдер обычно будет повторять запрос с экспоненциальной задержкой. Ваш сервис должен корректно обрабатывать такие повторные попытки и не «падать» от большого количества ретраев.
- Timeout и асинхронность – обрабатывайте webhook быстро (200 OK), а длительную логику выносите в очередь или фоновые задачи. Иначе провайдер может посчитать ваш сервер недоступным.
Как выбрать: callback URL или webhook?
Небольшой чеклист
| Ситуация | Рекомендация |
|---|---|
| Нужно получить результат одной конкретной операции (перевод, расчет) | Используйте callback URL |
| Нужно реагировать на все будущие события в системе (платежи, коммиты) | Используйте webhook |
| Интеграция с внешним сервисом, где вы не управляете его внутренней логикой | Предпочтительнее webhook |
| Вы контролируете и клиент, и сервер, и хотите простой синхронный подход | Можно обойтись без них (синхронный ответ) |
Webhook vs Callback совсем простыми словами
Callback – «перезвони мне, когда закончишь эту конкретную задачу» (один раз).
Webhook – «звони мне каждый раз, когда происходит вот такое событие» (многократно, настройка один раз, работает по HTTP между системами).
Резюме
Главное отличие: callback — это общий паттерн «вызову тебя позже», а webhook — это конкретная реализация этого паттерна по HTTP между сервисами, с многократными срабатываниями и заранее настроенной подпиской.
Выбирайте callback URL для разовых ответов на конкретный запрос, а webhook — для постоянного потока событий. Не забывайте про безопасность: проверяйте подписи, делайте обработчики идемпотентными и корректно работайте с повторными попытками.
Полезные ссылки для углубления
- GitHub Webhooks Documentation
- Stripe Webhooks Guide
- YooKassa Webhooks
- HMAC signature verification (пример)
Если вы только начинаете внедрять webhook‑и, рекомендую сначала изучить документацию вашего провайдера и реализовать простой endpoint с логированием — это поможет отладить интеграцию и избежать неприятных сюрпризов на проде.
