Вебхуки

Вебхуки отправляют события контента на ваш HTTPS-эндпоинт. Когда запись создаётся, обновляется или удаляется — CMS делает подписанный POST-запрос на настроенный URL.

Как настроить

  1. Откройте Вебхуки в боковой панели.
  2. Нажмите Добавить вебхук.
  3. Заполните:
    • Название — метка для списка.
    • URL приёмника — HTTPS-адрес, куда CMS будет отправлять POST.
    • Событияentity.created, entity.updated, entity.deleted. Можно выбрать несколько.
    • Типы контента — фильтр по типам контента. «Все типы контента» = без фильтра.
    • Активен — включить/выключить доставку.
  4. Сохраните. Сервер сгенерирует ключ подписи и покажет его один раз — скопируйте. Восстановить можно только ротацией ключа.

События

Событие Когда срабатывает
entity.created Создана новая запись любого типа.
entity.updated Изменена существующая запись.
entity.deleted Запись удалена.

Фильтр по типам контента сужает доставку: если выбрать только blog-post, вебхук сработает только для изменений постов, а не для всех записей.

Что получает приёмник

CMS отправляет POST с JSON-теллом:

{
  "id": "whev_a1b2c3",
  "tenant_id": "cf6efe09-...",
  "type": "entity.created",
  "entity_slug": "blog-post",
  "entity_id": "550e8400-...",
  "data": { "title": "Привет", "slug": "hello" },
  "user": { "id": "u-1", "username": "alice", "role": "editor" },
  "timestamp": "2026-08-11T12:00:00Z",
  "attempt": 1
}

Заголовки:

Заголовок Что содержит
Content-Type application/json
X-Dynamica-Signature HMAC-SHA256 подпись (см. ниже)
X-Dynamica-Delivery ID доставки — для идемпотентности
X-Dynamica-Event Тип события (entity.created)

Поле prev_data появляется только при entity.updated — содержит состояние до изменения. В остальных событиях этого поля нет.

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

Каждый запрос подписан HMAC-SHA256 с помощью ключа, который вы получили при создании вебхука. Подпись передаётся в заголовке X-Dynamica-Signature в формате t=<unix-секунды>,v1=<hex-HMAC>. HMAC считается от строки "<timestamp>.<сырое тело запроса>" — используйте исходные байты, не ре-сериализуйте JSON.

Проверка на стороне приёмника:

  1. Разбор t (unix-секунды) и v1 (hex-HMAC).
  2. Отклонить, если |now - t| > 5 минут.
  3. Вычислить HMAC от сырого тела запроса (не ре-сериализовать JSON!).
  4. Сравнить с v1 константным временем.

Пример (Node.js):

const crypto = require('crypto');

function verify(secret, rawBody, header) {
  const [tPart, v1Part] = header.split(',');
  const ts = tPart.split('=')[1];
  const v1 = v1Part.split('=')[1];

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(v1)
  );
}

Доставка и повторы

Параметр Значение
Таймаут 10 секунд
Попыток 8 (первая + 7 повторов)
Период ~24 часа
Параллельность 10 глобально, 3 на вебхук

Расписание задержек: 1 мин → 5 мин → 30 мин → 2 ч → 6 ч → 12 ч → 24 ч.

Поведение по HTTP-кодам ответа:

Код Действие
2xx Успех. Доставка завершена.
410 Вебхук деактивируется. Повторов нет.
4xx (кроме 410) Ошибка клиента. Повторов нет.
5xx Повтор. Каждый провал увеличивает счётчик.
Таймаут / сеть Повтор.

После 8 неудач доставка попадает в dead letter — терминальный статус.

Журнал доставок

В админке, под списком вебхуков — журнал последних 50 доставок. Для каждой: статус, событие, HTTP-код ответа, попытка, отправленный payload и тело ответа приёмника.

Статусы:

  • Успех — доставлено (2xx).
  • Повтор — ждёт следующей попытки.
  • Ожидает — в очереди.
  • Очередь недоставленных — все попытки исчерпаны.
  • Цепь разомкнута — предохранитель отключил доставку (5 минут).
  • Частичный сбой — запрос доставлен, но обработка команд не завершена.
  • Клиентская ошибка — 4xx, доставки прекращены.

Действия в журнале:

  • Тест — отправить тестовую доставку.
  • Повторить — повторить конкретную доставку.
  • Сменить ключ — сгенерировать новый ключ подписи.

Предохранитель

Если приёмник стабильно отвечает 5xx или не отвечает, предохранитель размыкает цепь: доставка приостанавливается на 5 минут. Условия: 20 последовательных неудач или ≥50% неудач из последних 50 запросов.

Лимиты

Количество вебхуков зависит от тарифа. Проверяется при создании — лимит превышен → вебхук не создастся.

Что дальше