ProBusinessEnterprise

Вебхуки: события и проверка подписи

Обзор

Вебхуки позволяют получать уведомления о событиях на платформе evntflo в реальном времени. При наступлении события (новая регистрация, успешная оплата, отмена мероприятия) evntflo отправляет HTTP POST запрос на ваш URL с данными события.

Вебхуки доступны на тарифах Pro, Business и Enterprise.

Настройка

Добавление webhook URL

  1. Откройте Настройки в боковом меню.
  2. Перейдите в раздел «Интеграции».
  3. Нажмите «Добавить вебхук».
  4. Укажите URL эндпоинта (HTTPS обязателен).
  5. Выберите типы событий, которые хотите получать.
  6. Нажмите «Сохранить».

После сохранения evntflo отправит тестовый запрос на указанный URL для проверки доступности.

Webhook secret

При создании вебхука система сгенерирует webhook secret -- строку для проверки подписи. Сохраните его в безопасном месте. Secret отображается только один раз.

Типы событий

СобытиеОписание
registration.createdСоздана новая регистрация
registration.updatedОбновлены данные регистрации (статус, поля)
payment.completedПлатёж успешно завершён
payment.refundedВыполнен возврат платежа
event.publishedМероприятие опубликовано
event.cancelledМероприятие отменено

Вы можете подписаться на все типы или выбрать только нужные в настройках интеграции.

Формат payload

Каждый вебхук отправляется как HTTP POST с телом в формате JSON.

Заголовки запроса

ЗаголовокОписание
Content-Typeapplication/json
X-Evntflo-EventТип события (например, registration.created)
X-Evntflo-SignatureHMAC-SHA256 подпись тела запроса
X-Evntflo-TimestampUnix timestamp отправки (секунды)
X-Evntflo-Request-IdУникальный идентификатор запроса

Структура тела

{
  "event": "registration.created",
  "timestamp": "2026-06-30T14:30:00Z",
  "requestId": "req_01912345abcdef",
  "data": {
    "id": "01912345-6789-7abc-def0-123456789abc",
    "event_id": "01900000-0000-7000-0000-000000000001",
    "status": "registered",
    "fields": {
      "registrant_email": "user@example.com",
      "first_name": "Ivan",
      "last_name": "Petrov"
    },
    "created_at": "2026-06-30T14:30:00Z"
  }
}

Поле requestId присутствует в каждом вебхуке. Используйте его для дедупликации и при обращении в поддержку.

Примеры payload по типам событий

registration.created

{
  "event": "registration.created",
  "timestamp": "2026-06-30T14:30:00Z",
  "requestId": "req_01912345abcdef",
  "data": {
    "id": "01912345-6789-7abc-def0-123456789abc",
    "event_id": "01900000-0000-7000-0000-000000000001",
    "event_slug": "tech-conference-2026",
    "status": "registered",
    "ticket_definition_id": "01900000-0000-7000-0000-000000000010",
    "fields": {
      "registrant_email": "user@example.com",
      "first_name": "Ivan",
      "last_name": "Petrov",
      "company": "Acme Corp"
    },
    "created_at": "2026-06-30T14:30:00Z"
  }
}

payment.completed

{
  "event": "payment.completed",
  "timestamp": "2026-06-30T14:31:00Z",
  "requestId": "req_01912345abcdf0",
  "data": {
    "id": "01912345-6789-7abc-def0-000000000099",
    "registration_id": "01912345-6789-7abc-def0-123456789abc",
    "amount": 5000,
    "currency": "RUB",
    "method": "card",
    "gateway": "yookassa",
    "idempotency_key": "idem_abc123",
    "completed_at": "2026-06-30T14:31:00Z"
  }
}

event.cancelled

{
  "event": "event.cancelled",
  "timestamp": "2026-06-30T15:00:00Z",
  "requestId": "req_01912345abcdf1",
  "data": {
    "id": "01900000-0000-7000-0000-000000000001",
    "slug": "tech-conference-2026",
    "title": "Tech Conference 2026",
    "cancelled_at": "2026-06-30T15:00:00Z",
    "reason": "Venue unavailable"
  }
}

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

Каждый вебхук подписывается с помощью HMAC-SHA256. Проверка подписи гарантирует, что запрос отправлен evntflo, а не злоумышленником.

Алгоритм

  1. Получите значения заголовков X-Evntflo-Timestamp и X-Evntflo-Signature.
  2. Сформируйте строку для подписи: <timestamp>.<body>, где body -- raw body запроса.
  3. Вычислите HMAC-SHA256 от этой строки с вашим webhook secret.
  4. Сравните результат с X-Evntflo-Signature в hex-формате.

Пример на Node.js

const crypto = require('crypto');

function verifySignature(body, timestamp, signature, secret) {
  const payload = `${timestamp}.${body}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  // Constant-time сравнение для защиты от timing-атак
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Пример на Python

import hmac
import hashlib

def verify_signature(body: str, timestamp: str, signature: str, secret: str) -> bool:
    payload = f"{timestamp}.{body}"
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Защита от replay-атак

Проверяйте X-Evntflo-Timestamp: если он старше 5 минут -- отклоняйте запрос. Это предотвращает повторное использование перехваченных вебхуков.

Политика повторных попыток

Если ваш эндпоинт не ответил HTTP 2xx, evntflo повторяет отправку:

ПопыткаЗадержка
1Немедленно
2Через 1 минуту
3Через 5 минут
4Через 30 минут

Если все 4 попытки (первоначальная + 3 повтора) неуспешны, событие помечается как failed. Вы увидите список неуспешных вебхуков в разделе Настройки - Интеграции - История доставки.

Что считается успехом

  • HTTP 200, 201, 202, 204 -- доставка считается успешной.
  • Таймаут: ответ должен быть получен в течение 10 секунд.

Что считается ошибкой

  • HTTP 4xx (кроме 410) -- повторная отправка, возможна проблема на стороне получателя.
  • HTTP 5xx -- повторная отправка с задержкой.
  • Таймаут (нет ответа за 10 секунд) -- повторная отправка.
  • HTTP 410 (Gone) -- вебхук автоматически отключается, повторов не будет.

Дедупликация

Из-за повторных попыток ваш эндпоинт может получить одно и то же событие несколько раз. Используйте requestId из payload для дедупликации:

  1. При получении вебхука проверьте, обрабатывали ли вы уже requestId.
  2. Если да -- верните HTTP 200 без повторной обработки.
  3. Если нет -- обработайте и сохраните requestId.

Рекомендации

Быстрый ответ

Отправляйте HTTP 200 сразу после получения запроса. Длительную обработку выполняйте асинхронно (очередь, фоновая задача). Это снижает риск таймаута и повторных отправок.

Идемпотентность

Проектируйте обработчик так, чтобы повторная обработка одного события не приводила к дублированию действий (двойная отправка email, повторное списание и т.д.).

Логирование

Сохраняйте requestId, X-Evntflo-Event и timestamp каждого полученного вебхука. Это поможет при отладке и обращении в поддержку.

Безопасность

  • Принимайте вебхуки только по HTTPS.
  • Всегда проверяйте подпись через HMAC-SHA256.
  • Проверяйте timestamp для защиты от replay-атак.
  • Храните webhook secret в переменных окружения, не в коде.

Частые вопросы

Какие тарифы поддерживают вебхуки?
Вебхуки доступны на тарифах Pro, Business и Enterprise. На бесплатном тарифе вебхуки недоступны -- используйте ручной экспорт или публичное API.
Сколько раз evntflo повторяет отправку при ошибке?
Три попытки с экспоненциальной задержкой: через 1 минуту, через 5 минут, через 30 минут. Если все три попытки неуспешны -- событие помечается как failed.
Как проверить подпись вебхука?
Вычислите HMAC-SHA256 от тела запроса с вашим webhook secret и сравните с заголовком X-Evntflo-Signature. Используйте constant-time сравнение для защиты от timing-атак.
Можно ли настроить несколько URL для вебхуков?
Да. В разделе Настройки - Интеграции можно добавить несколько URL и выбрать, какие типы событий отправлять на каждый из них.