Вебхуки
Pingera может отправлять HTTP-запросы на ваш сервер при событиях на платформе. Вебхуки отправляются в двух случаях:
- Канал оповещений типа Webhook — при срабатывании и разрешении оповещений по проверкам, а также при пропуске и восстановлении пульсаров. Настройка описана в разделе Каналы оповещений.
- Подписчик Статус Страницы с типом webhook — при создании и обновлении инцидентов. Настройка описана в разделе Подписчики.
Запрос
| Параметр | Канал оповещений | Подписчик Статус Страницы |
|---|---|---|
| Метод | POST по умолчанию, можно выбрать PUT или PATCH | POST |
Content-Type | application/json | application/json |
| Свои заголовки | Да, задаются в настройках канала | Нет |
| Таймаут | 30 секунд, настраивается в канале | 30 секунд |
Доставка считается успешной, если ваш сервер ответил кодом 2xx. Перенаправления (3xx) выполняются автоматически.
Структура сообщения
Все вебхуки отправляются в общей обёртке. Данные события находятся в поле incident_data — это название используется для всех типов событий, включая оповещения по проверкам.
| Поле | Тип | Описание |
|---|---|---|
message_purpose | string | Тип сообщения: alert_notification, incident_created или incident_updated. |
recipient | string | URL, на который отправлен вебхук. |
incident_data | object | Данные события. Формат зависит от типа события, см. ниже. |
context | object | Связанные идентификаторы. Для оповещений — пустой объект. |
created_at | string | Время создания сообщения, ISO 8601 в UTC. |
reference_id | string | Идентификатор события: ID оповещения или связка инцидента и подписчика. Может быть null. |
timestamp | integer | Время отправки запроса, Unix-время в секундах. Меняется при повторных попытках. |
Как определить тип события
message_purpose | Условие | Событие |
|---|---|---|
alert_notification | incident_data.notification_type == "alert" | Оповещение по проверке сработало |
alert_notification | incident_data.notification_type == "resolution" | Оповещение по проверке разрешено |
alert_notification | incident_data.alert.check_type == "heartbeat" | Пульсар пропустил сигнал или восстановился |
alert_notification | incident_data.notification_type == "test" | Тестовое сообщение |
incident_created, incident_updated | — | Инцидент на Статус Странице |
Оповещение по проверке
Срабатывание
{
"message_purpose": "alert_notification",
"recipient": "https://example.com/pingera-webhook",
"incident_data": {
"alert_id": "q8w2e4r6t1y3",
"notification_type": "alert",
"channel_name": "Production Webhook",
"alert": {
"title": "Check 'API Health' failed 3 times consecutively",
"description": "The monitoring check 'API Health' has failed 3 times in a row.",
"severity": "high",
"check_name": "API Health",
"organization_name": "Acme",
"rule_name": "API Health - critical",
"fired_at": "2026-10-08T10:30:45.123456",
"alert_metadata": {
"check_type": "api",
"condition": "consecutive_failures",
"condition_parameters": {"count": 3},
"last_result_status": "failed",
"last_result_time": "2026-10-08T10:30:41.987654",
"response_time": 30012,
"error_message": "Request timeout"
}
}
},
"context": {},
"created_at": "2026-10-08T10:30:45.456789",
"reference_id": "q8w2e4r6t1y3",
"timestamp": 1791455445
}
Поле incident_data | Описание |
|---|---|
alert_id | ID оповещения. Одинаковый для срабатывания и разрешения. |
notification_type | alert — срабатывание, resolution — разрешение. |
channel_name | Название канала оповещений. |
alert.severity | Критичность: low, medium, high, critical. |
alert.fired_at | Время срабатывания, ISO 8601 в UTC. |
alert.alert_metadata | Условие правила и данные последнего результата проверки. Поля last_result_*, response_time и error_message есть, только если у проверки уже есть результаты. |
alert.alert_metadata.condition | Условие правила: check_failed, consecutive_failures, uptime_below_threshold, check_timeout, check_degraded. |
Разрешение
Когда проверка восстанавливается, приходит сообщение с notification_type: "resolution". В alert добавляются поля resolved_at и duration:
{
"message_purpose": "alert_notification",
"recipient": "https://example.com/pingera-webhook",
"incident_data": {
"alert_id": "q8w2e4r6t1y3",
"notification_type": "resolution",
"channel_name": "Production Webhook",
"alert": {
"title": "Check 'API Health' failed 3 times consecutively",
"description": "The monitoring check 'API Health' has failed 3 times in a row.",
"severity": "high",
"check_name": "API Health",
"organization_name": "Acme",
"rule_name": "API Health - critical",
"fired_at": "2026-10-08T10:30:45.123456",
"resolved_at": "2026-10-08T10:35:22.654321",
"duration": "0:04:37.530865",
"alert_metadata": { ... }
}
},
"context": {},
"created_at": "2026-10-08T10:35:22.700000",
"reference_id": "q8w2e4r6t1y3",
"timestamp": 1791455722
}
duration — длительность оповещения в формате ЧЧ:ММ:СС.мкс.
Оповещение по пульсару
Отправляется, когда пульсар пропустил ожидаемый сигнал (alert_type: "missed_ping") и когда сигналы возобновились (alert_type: "recovered").
{
"message_purpose": "alert_notification",
"recipient": "https://example.com/pingera-webhook",
"incident_data": {
"test": false,
"channel_name": "Production Webhook",
"alert": {
"title": "Nightly backup",
"message": "Heartbeat check 'Nightly backup' has missed its expected ping. Expected every 86400 seconds, last ping: 2026-10-07 03:00:12 UTC",
"check_id": "h7j3k9l2m4n6",
"check_name": "Nightly backup",
"check_type": "heartbeat",
"alert_type": "missed_ping",
"status": "down",
"last_ping_at": "2026-10-07T03:00:12.345678",
"ping_url": "https://api.pingera.ru/v1/heartbeats/h7j3k9l2m4n6/ping",
"organization_id": "o1p2q3r4s5t6",
"period_seconds": 86400,
"grace_seconds": 600,
"timestamp": "2026-10-08T03:10:12.345678Z"
}
},
"context": {},
"created_at": "2026-10-08T03:10:12.400000",
"reference_id": null,
"timestamp": 1791428412
}
Поле incident_data.alert | Описание |
|---|---|
alert_type | missed_ping — сигнал пропущен, recovered — сигналы возобновились. |
status | Статус пульсара: down или up. |
last_ping_at | Время последнего полученного сигнала или null. |
period_seconds, grace_seconds | Ожидаемый период сигналов и льготный период в секундах. |
Тестовое сообщение
Проверить настройки канала можно запросом POST /v1/alerts/channels/{channel_id}/test для сохранённого канала или POST /v1/alerts/channels/test для ещё не сохранённой конфигурации. Тестовое сообщение имеет notification_type: "test" и test: true:
{
"message_purpose": "alert_notification",
"recipient": "https://example.com/pingera-webhook",
"incident_data": {
"test": true,
"notification_type": "test",
"channel_name": "Production Webhook",
"alert": {
"title": "Test notification",
"description": "This is a test notification from Pingera. If you received it, the channel is configured correctly.",
"severity": "low",
"check_name": "Test check",
"organization_name": "Acme",
"fired_at": "2026-10-08T10:00:00.000000"
}
},
"context": {},
"created_at": "2026-10-08T10:00:00.000000",
"reference_id": null,
"timestamp": 1791453600
}
Особенности тестовой отправки:
- Таймаут — не более 10 секунд, перенаправления не выполняются.
- URL, указывающие на частные и зарезервированные IP-адреса, отклоняются.
- Не более 30 тестовых сообщений в минуту на организацию. При превышении API вернёт
429. - Повторных попыток нет: результат возвращается сразу в ответе API.
Инцидент на Статус Странице
Подписчики с типом webhook получают сообщения при создании и обновлении инцидентов.
{
"message_purpose": "incident_created",
"recipient": "https://example.com/status-webhook",
"incident_data": {
"company_url": "https://example.com",
"company_logo": "https://example.com/logo.png",
"incident_name": "Повышенное время ответа API",
"incident_status": "Расследуется",
"incident_body": "Мы наблюдаем замедление ответов API и выясняем причину.",
"incident_update_time": "08 октября 2026 13:18 GMT+03:00",
"incident_id": "7susdsaqfm6l",
"page_domain": "status.example.com",
"affected_components": "API, Личный кабинет"
},
"context": {
"page_id": "5rs9dvpvyyp8",
"incident_id": "7susdsaqfm6l",
"incident_update_id": "si78yj8ics6e",
"subscriber_id": "b2c4d6f8h0j2"
},
"created_at": "2026-10-08T10:18:49.320501",
"reference_id": "incident_7susdsaqfm6l_subscriber_b2c4d6f8h0j2",
"timestamp": 1791454729
}
Поле incident_data | Описание |
|---|---|
incident_name | Название инцидента. |
incident_status | Статус инцидента, переведённый на язык Статус Страницы. |
incident_body | Текст обновления инцидента. |
incident_update_time | Время обновления в виде готовой строки на языке Статус Страницы. |
incident_id | ID инцидента. |
page_domain | Домен Статус Страницы. |
affected_components | Затронутые компоненты через запятую. |
incident_status и incident_update_time предназначены для показа людям. Для автоматической обработки используйте context.incident_id и context.incident_update_id и при необходимости запрашивайте актуальные данные инцидента через API.
Повторные попытки
Если ваш сервер не ответил кодом 2xx или не уложился в таймаут, Pingera повторит отправку. Всего делается до 5 попыток, интервал между ними растёт экспоненциально: примерно 2, 4, 8 и 16 минут.
Из-за повторов одно и то же событие может прийти несколько раз. Чтобы обработать его один раз, используйте как ключ:
- для оповещений по проверкам — пару
incident_data.alert_idиincident_data.notification_type; - для инцидентов —
context.incident_update_idиcontext.subscriber_id.
Рекомендации по приёму
- Отвечайте кодом
2xxкак можно быстрее, а тяжёлую обработку выполняйте асинхронно. - Используйте HTTPS.
- Pingera не подписывает вебхуки. Чтобы убедиться, что запрос пришёл от Pingera, добавьте в канал оповещений собственный заголовок с секретным значением (например,
X-Webhook-Token) и проверяйте его на своей стороне. Для вебхуков подписчиков используйте секретный токен в URL. - Не полагайтесь на порядок полей и будьте готовы к появлению новых полей в сообщениях.