Skip to main content

Вебхуки

При каждом событии жизненного цикла письма MailInfra шлёт HTTP POST на URL, указанный в дашборде. Это альтернатива поллингу GET /v1/emails/{id}/events.

Создание, редактирование, ротация секрета и тестовая отправка — в дашборде: Проект → Вебхуки.

События

ТипКогда срабатывает
queuedПисьмо принято в очередь
sendingПередача в MTA началась
sentПередано SMTP-серверу получателя
deliveredПисьмо доставлено
clickedКлик по отслеживаемой ссылке
bouncedНедоставка; адрес попадает в список подавления
complainedЖалоба на спам; адрес попадает в список подавления
failedВнутренняя ошибка отправки

В дашборде можно подписаться на все события или на конкретное подмножество.

Формат входящего запроса

Заголовки

ЗаголовокЗначение
Content-Typeapplication/json
User-AgentMailInfra-Webhook/1.0
X-MailInfra-Event-IdUUID события — для дедупликации между retry
X-MailInfra-SignatureHMAC-SHA256 — обязательно проверяйте

Тело

{
"id": "evt_018e1b7a-2c3d-7000-8d4e-5f6a7b8c9d0e",
"type": "email.delivered",
"created_at": "2026-05-11T20:15:30.123456Z",
"data": {
"email": {
"id": "018e1b7a-1111-7000-aaaa-111111111111",
"from": "hello@mail.example.ru",
"to": ["user@gmail.com"],
"subject": "Добро пожаловать!",
"tags": ["welcome"],
"status": "DELIVERED"
},
"event": {}
}
}

type всегда в формате email.<тип>. Для тестового пинга из дашборда — test.ping:

{
"id": "evt_test_ping",
"type": "test.ping",
"created_at": "2026-05-11T20:00:00Z",
"data": { "message": "This is a test webhook event from MailInfra" }
}

Что должен возвращать ваш endpoint

  • Любой 2xx в течение 10 секунд — событие считается обработанным.
  • Тяжёлую обработку выносите в фоновую очередь: ответьте 200 сразу, обрабатывайте после.
  • Не возвращайте 2xx, если данные не приняли — иначе вы потеряете событие.

Повторы и автоотключение

Если ваш endpoint вернул не-2xx или превысил таймаут, MailInfra повторяет доставку с экспоненциальной задержкой:

ПопыткаЗадержка
2-я1 минута
3-я5 минут
4-я30 минут
5-я2 часа
6-я6 часов

После 5 последовательных неудач вебхук автоматически деактивируется. В дашборде он отобразится как «отключён» — там же его можно снова активировать после починки endpoint.

Чек-лист интеграции

  • URL использует HTTPS
  • Подпись проверяется на сыром теле запроса (до парсинга JSON)
  • X-MailInfra-Event-Id логируется и используется для дедупликации
  • Endpoint отвечает 2xx в пределах 10 секунд
  • Тяжёлая обработка вынесена в фоновую задачу
  • Секрет вебхука хранится в переменных окружения

Управление вебхуками

CRUD вебхуков, тестовый запуск и ротация секрета — часть Management API. Базовый префикс: /v1/organizations/{organization_id}/projects/{project_id}/webhooks.

МетодПутьМинимальная рольЧто делает
GET/webhooksVIEWERСписок вебхуков проекта
POST/webhooksDEVELOPERСоздать вебхук, в ответе показывается secret
GET/webhooks/{id}VIEWERДетали вебхука без секрета
PATCH/webhooks/{id}DEVELOPERИзменить URL, события или is_active
POST/webhooks/{id}/rotate-secretDEVELOPERСгенерировать новый секрет; старый сразу инвалидируется
POST/webhooks/{id}/testDEVELOPERПослать на endpoint синтетическое событие test.ping
DELETE/webhooks/{id}DEVELOPERУдалить вебхук

Создать вебхук

POST /v1/organizations/{organization_id}/projects/{project_id}/webhooks
Authorization: Bearer <session_token>
Content-Type: application/json
{
"url": "https://api.example.com/hooks/mailinfra",
"events": ["delivered", "bounced", "complained"]
}
ПолеТипОписание
urlstring (HTTPS)Куда слать POST с событием
eventsstring[]Подписанные события: 1–20 значений из таблицы выше

Ответ 201 Created:

{
"data": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"project_id": "...",
"url": "https://api.example.com/hooks/mailinfra",
"events": ["delivered", "bounced", "complained"],
"is_active": true,
"created_at": "2026-05-12T09:00:00Z",
"updated_at": "2026-05-12T09:00:00Z",
"secret": "whsec_a3f4e1c2d7b89012345678901234567890abcdef1234567890abcdef12345678"
}
}
Секрет показывается один раз

secret возвращается только при создании и при ротации. Сохраните его как пароль — повторно получить нельзя. Без секрета вы не сможете проверять подпись.

Изменить вебхук

PATCH /v1/.../webhooks/{webhook_id}
Authorization: Bearer <session_token>
Content-Type: application/json
{
"events": ["delivered", "bounced"],
"is_active": true
}

Любые из полей url, events, is_active опциональны — обновляется только то, что передали. Чаще всего is_active: true нужен после автоматического отключения вебхука из-за серии неудач.

Тестовый прогон

POST /v1/.../webhooks/{webhook_id}/test
Authorization: Bearer <session_token>
{
"data": {
"success": true,
"http_status": 200,
"error": null
}
}

MailInfra сделает POST на ваш url со специальным событием test.ping и подпишет его текущим секретом. Удобно дёргать из CI после деплоя обработчика.

Ротация секрета

POST /v1/.../webhooks/{webhook_id}/rotate-secret
Authorization: Bearer <session_token>
{ "data": { "secret": "whsec_<новые_64_hex>" } }

Старый секрет немедленно перестаёт быть валидным — обновите переменную окружения до следующего события, иначе обработчик начнёт отвергать входящие как Invalid signature.