POST-запрос на ваш URL с данными события.
200, 201 или 202 (таймаут ответа — 15 секунд).Как это работает
Событие фиксируется
PaymentCompleted) с таймстемпом и параметрами инициатора.Поиск активных эндпоинтов
Сборка полезной нагрузки
data,
единый idempotencyKey и timestamp. Лишние поля вырезаются по строгой схеме (allow-list).Формат сообщения
Тело запроса — JSON-объект следующей структуры:Проверка подписи
В каждом запросе передаётся заголовокsignature — это HMAC-SHA256 (hex) от сырого тела запроса,
подписанного секретным ключом вашего эндпоинта.
Доставка и повторные попытки
| Параметр | Значение |
|---|---|
| HTTP-метод | POST |
| Content-Type | application/json |
| Заголовок подписи | signature (HMAC-SHA256, hex) |
| Таймаут ответа | 15 секунд |
| Успешные коды | 200, 201, 202 |
| Число попыток | до 5 |
| Задержки между попытками | ~11 → 22 → 44 → 88 → 176 минут |
| Порядок доставки | не гарантируется |
| Дедупликация | по idempotencyKey на вашей стороне |
200/201/202, а также таймаут или сетевая ошибка считаются неуспехом и приводят к
повторной попытке. После 5 неудачных попыток событие помечается как failed и больше не отправляется.Управление эндпоинтами
Эндпоинты вебхуков настраиваются в админ-панели школы (раздел настроек). Для каждого эндпоинта задаётся:url— HTTPS-адрес приёмника (до 255 символов);events— список событий, на которые он подписан;active— флаг активности (по умолчаниюtrue);note— произвольная заметка;secretKey— секрет для проверки подписи, генерируется автоматически при создании эндпоинта.
secretKey создаётся вместе с эндпоинтом и доступен в
настройках вебхука в админ-панели школы. Скопируйте его и сохраните в переменных окружения вашего
сервиса (в примерах ниже — EXODE_WEBHOOK_SECRET). Если секрет не отображается — запросите его у
поддержки.Поддерживаемые события
Ниже — события, которые реально доставляются, и структура их поляdata. Вложенные сущности
(user, profile, course, payment и др.) описаны в справочнике объектов.
UserSignedUp — регистрация пользователя
UserSignedUp — регистрация пользователя
data:user— объект пользователя.profile— карточка профиля (null, если не заполнена).states.utmSignupParams— объект UTM-меток первичного визита (опционально).
UserAcquainted — завершён онбординг
UserAcquainted — завершён онбординг
data идентична UserSignedUp
(user, profile, states.utmSignupParams).UserTgConnected — привязан Telegram
UserTgConnected — привязан Telegram
data:user— объект пользователя (с актуальнымtgId).profile— карточка профиля (опционально).prevTgId— предыдущийtgIdдля отслеживания перепривязки (number | null).
CourseProgressChanged — изменился прогресс по уроку
CourseProgressChanged — изменился прогресс по уроку
data:user— пользователь с профилем.course— объект курса.product— продукт курса (опционально).groups— массив групп пользователя в курсе (опционально).status— новый статус урока (CourseProgressLessonStatus, опционально).lessonId— ID урока (опционально).
CourseCompleted — курс завершён
CourseCompleted — курс завершён
data:user— пользователь с профилем.course— объект курса.product— продукт курса (опционально).groups— массив групп (опционально).
CourseLessonPracticeCompleted — пройдена практика
CourseLessonPracticeCompleted — пройдена практика
data:user— пользователь с профилем.course— курс (опционально).lesson— урок (опционально).practice— параметры практики (опционально).attempt— попытка прохождения с баллами и статусом (опционально).variantId— ID варианта (опционально).
PaymentCompleted — оплата прошла успешно
PaymentCompleted — оплата прошла успешно
data.payment — объект платежа с полным деревом: invoice
(счёт), invoice.user (покупатель с профилем и школой), invoice.products (позиции с продуктом/курсом,
ценой и скидкой), acquiring (эквайринг и провайдер, без секретов). Денежные поля — числа.ProductEnrolledToFree — выдан бесплатный доступ
ProductEnrolledToFree — выдан бесплатный доступ
data:user— пользователь.profile— карточка профиля (опционально).access— объект доступа (опционально).product— продукт (опционально).course— курс (опционально).
ProductEnrolledViaLms — доступ выдан вручную (LMS)
ProductEnrolledViaLms — доступ выдан вручную (LMS)
data идентична ProductEnrolledToFree (user, profile, access, product, course).ProductEnrolledViaPayment — доступ выдан после оплаты
ProductEnrolledViaPayment — доступ выдан после оплаты
data идентична ProductEnrolledToFree (user, profile, access, product, course).UserSignedIn, UserLoggedOut, UserJoinedByReferral, UserCreatedViaLms,
CourseLessonPracticeDetailedSent, CourseLessonPracticeAutoVerifySent, ProductRefundCompleted,
ProductAccessSubscriptionEnding7Days и ProductAccessSubscriptionEnding1Day можно подписаться, но
формальный контракт data для них ещё не зафиксирован — состав полезной нагрузки не гарантируется.
Перед использованием сверьтесь с поддержкой.SchoolCreated также доставляется, но только на системном уровне и недоступно для подписки
продавцом.Пример: PaymentCompleted
Тело ниже — реальный пример тестовой отправки (синтетические значения, точный состав полей):Диагностика
Повторные попытки
Повторные попытки
idempotencyKey. Задержки отсчитываются от предыдущей
неудачной попытки (≈11 / 22 / 44 / 88 / 176 минут). Верните успешный код, чтобы остановить повторы.Временное отключение
Временное отключение
active = false, чтобы приостановить доставку без потери конфигурации и секретного ключа.Логирование
Логирование
event, timestamp, idempotencyKey и результат проверки подписи — это ускорит сверку с
нашей стороной при разборе инцидентов.