Skip to Content
ДокументацияСобытия и вебхуки

События и вебхуки

Вам не нужно непрерывно опрашивать (poll) API, чтобы узнавать о тревогах и событиях отправок. Вы регистрируете HTTPS-адрес, и при возникновении события Frigolive отправляет на него подписанный POST-запрос.

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

Настройка

Эндпоинты настраиваются в разделе Настройки → Вебхуки (Settings → Webhooks) панели Frigolive. При сохранении адреса генерируется секрет подписи (signing secret), который отображается ровно один раз. Сохраните его в защищенном хранилище секретов вашего сервиса-обработчика.

На этом же экране вы можете отправить тестовое событие и просмотреть последние 100 попыток доставки с кодами ответов и сообщениями об ошибках.

Публикуемые события

СобытиеКогда происходитТело данных
alarm.createdВозникла новая тревогаЗапись тревоги (alarm record)
alarm.resolvedТревога помечена как решеннаяЗапись тревоги (alarm record)
shipment.createdСоздана новая отправкаЗапись отправки (shipment record)
shipment.completedОтправка завершенаЗапись отправки (shipment record)

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

Формат запроса

POST /your-receiver-address HTTP/1.1 Content-Type: application/json; charset=utf-8 User-Agent: Frigolive-Webhooks/1.0 X-Frigolive-Event: alarm.created X-Frigolive-Event-ID: 7126f58a-77c7-4d50-aa87-d1dd99297713 X-Frigolive-Delivery-ID: 0fbc2c15-10ab-4b75-a59e-043b23614b60 X-Frigolive-Timestamp: 1785312000 X-Frigolive-Signature: v1=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 { "id": "7126f58a-77c7-4d50-aa87-d1dd99297713", "type": "alarm.created", "created_at": "2026-07-27T11:42:00Z", "data": { "id": "0fbc2c15-10ab-4b75-a59e-043b23614b60", "device_id": "a6532895-026f-4dad-9f89-432a33e93bc0", "shipment_id": 481, "type": "TEMPERATURE", "severity": "WARNING", "source": "THRESHOLD", "message": "Temperature above configured maximum.", "resolved": false, "created_at": "2026-07-27T11:42:00Z", "resolved_at": null } }

Проверка подписи

Никогда не доверяйте телу запроса до проверки подписи

Ваш эндпоинт доступен в публичном интернете, и отправить запрос на него может кто угодно. Проверка подписи — единственное доказательство того, что запрос действительно отправлен Frigolive и не был изменен при передаче.

Подписываемая строка имеет формат "{timestamp}.{raw body}" и подписывается алгоритмом HMAC-SHA256. Используйте исходное тело запроса (raw body): если вы распарсите JSON и затем сериализуете его обратно, байты изменятся, и подпись не совпадет.

import hashlib import hmac import time TOLERANCE_SECONDS = 300 # 5 минут def verify(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool: # 1) Окно времени: предотвращает атаки повторного воспроизведения (replay attacks). if abs(time.time() - int(timestamp)) > TOLERANCE_SECONDS: return False # 2) Пересчет подписи. signed = f"{timestamp}.".encode() + raw_body expected = "v1=" + hmac.new( secret.encode(), signed, hashlib.sha256 ).hexdigest() # 3) Сравнение за постоянное время для предотвращения timing-атак. return hmac.compare_digest(expected, signature)

Аналог на Node.js:

import { createHmac, timingSafeEqual } from "node:crypto"; export function verify(rawBody: Buffer, timestamp: string, signature: string, secret: string) { if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; const expected = "v1=" + createHmac("sha256", secret) .update(Buffer.concat([Buffer.from(`${timestamp}.`), rawBody])) .digest("hex"); const a = Buffer.from(expected); const b = Buffer.from(signature); return a.length === b.length && timingSafeEqual(a, b); }

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

Возвращайте статус 2xx в течение 10 секунд. Тело ответа не анализируется; пустой ответ вполне допустим.

Не выполняйте тяжелую обработку синхронно: поместите событие в собственную очередь и немедленно верните 200. Медленный ответ приведет к таймауту и лишним повторным попыткам отправки.

Повторные попытки и идемпотентность

ОтветПоведение
2xxУспешно, доставка завершена.
429 или 5xxПовтор до 6 раз с экспоненциальной задержкой и джиттером (jitter).
Любой другой 4xxСчитается постоянной ошибкой, повторные попытки не выполняются.
Ошибка соединения / таймаутПовторная попытка.
Вы можете получить одно и то же событие дважды

Если ваш ответ потерялся в сети, Frigolive повторит попытку доставки. X-Frigolive-Event-ID не изменяется между попытками — сохраняйте его и пропускайте уже обработанные события. Заголовок X-Frigolive-Delivery-ID уникален для каждой попытки и используется для диагностики.

После 20 последовательных неудачных попыток доставки эндпоинт автоматически отключается, а в панели управления появляется предупреждение. После устранения неполадок вы можете снова включить его на том же экране.

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

Вы можете сгенерировать новый секрет подписи в панели управления. Новый секрет вступает в силу немедленно; если нет ожидающих доставки событий, подписанных старым секретом, процесс пройдет без задержек. Чтобы полностью исключить разрыв, настройте сервис-обработчик на прием обоих секретов в период перехода.

Чек-лист безопасности

  1. Используйте исключительно https:// — панель отклоняет незащищенный http://.
  2. Проверяйте подпись для каждого запроса; никогда не обрабатывайте непроверенные данные.
  3. Устанавливайте допустимое отклонение времени (timestamp tolerance) не более 5 минут.
  4. Храните секрет подписи в менеджере секретов, ни в коем случае не в коде или логах.
  5. Выполняйте дедупликацию по заголовку X-Frigolive-Event-ID.
  6. Размещайте эндпоинт по трудноугадываемому URL-пути.