Вебхуки
Управление вебхуками магазина.
Структура payload
При наступлении события система отправляет HTTP POST-запрос на зарегистрированный URL с JSON-телом.
Конкретный вариант определяется значением поля event:
event |
Схема payload | Описание |
|---|---|---|
ORDER_STATUS_CHANGED |
WebhookOrderStatusChangedPayload |
Изменение статуса заказа. |
ORDER_PAYMENT_STATUS_CHANGED |
WebhookOrderPaymentStatusChangedPayload |
Изменение статуса оплаты заказа. |
ORDER_DELIVERY_STATUS_CHANGED |
WebhookOrderDeliveryStatusChangedPayload |
Изменение статуса доставки заказа. |
CUSTOMER_CHANGED |
WebhookCustomerChangedPayload |
Изменение данных клиента. |
CART_UPDATED |
WebhookCartUpdatedPayload |
Изменение корзины клиента. |
WEBHOOK_VALIDATE |
WebhookValidatePayload |
Запрос валидации URL при активации. |
Поля payload
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
event_id |
string (uuid) |
Уникальный ID события. Используется для идемпотентной обработки. Повторная доставка приходит с тем же event_id. |
✓ |
event |
string (enum) |
Тип события: ORDER_STATUS_CHANGED, ORDER_PAYMENT_STATUS_CHANGED, ORDER_DELIVERY_STATUS_CHANGED, CUSTOMER_CHANGED или WEBHOOK_VALIDATE(при вызове POST /v1/webhooks/{webhook_id}/validate?activate=true). |
✓ |
occurred_at |
string (date-time) |
Время возникновения события. | ✓ |
data |
object |
Данные события. |
Поля data для ORDER_STATUS_CHANGED
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
order_id |
string (uuid) |
ID заказа. | ✓ |
customer_id |
string (uuid) |
ID клиента, который оформил заказ. Данные клиента — GET /v1/customers/{customer_id}. |
✓ |
new_status |
OrderStatus |
Новый статус заказа. Подробнее см. в разделе Заказы. |
✓ |
Поля data для ORDER_PAYMENT_STATUS_CHANGED
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
order_id |
string (uuid) |
ID заказа. | ✓ |
customer_id |
string (uuid) |
ID клиента, который оформил заказ. Данные клиента — GET /v1/customers/{customer_id}. |
✓ |
new_payment_status |
PaymentStatus |
Новый статус оплаты. Подробнее см. в разделе Заказы. |
✓ |
Поля data для ORDER_DELIVERY_STATUS_CHANGED
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
order_id |
string (uuid) |
ID заказа. | ✓ |
customer_id |
string (uuid) |
ID клиента, который оформил заказ. Данные клиента — GET /v1/customers/{customer_id}. |
✓ |
chunk_id |
integer |
ID части доставки заказа (у заказа может быть несколько отправлений). | ✓ |
new_delivery_status |
DeliveryStatus |
Новый статус доставки. Подробнее см. в разделе Заказы. |
✓ |
Поля data для CUSTOMER_CHANGED
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
customer_id |
string (uuid) |
ID клиента. | ✓ |
Поля data для CART_UPDATED
| Поле | Тип | Описание | Обязательное |
|---|---|---|---|
customer_id |
string (uuid) |
ID клиента, чья корзина изменилась. Состав корзины — GET /v1/customers/{customer_id}/cart. |
✓ |
События по одной корзине схлопываются: серия изменений (включая очистку корзины) приходит одним событием, новое событие по одной корзине формируется не чаще раза в окно (по умолчанию 15 минут). Повторная доставка события может прийти позже следующего события по той же корзине. Событие приходит с задержкой до окна после изменения, поэтому актуальный состав корзины запрашивайте в момент обработки события.
Пример payload для ORDER_STATUS_CHANGED:
{
"event_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"event": "ORDER_STATUS_CHANGED",
"occurred_at": "2024-01-15T10:30:00Z",
"data": {
"order_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"customer_id": "019b21da-0a3e-7c41-9f2b-5e8d1c7a4b60",
"new_status": "DELIVERED"
}
}
Пример payload для ORDER_PAYMENT_STATUS_CHANGED:
{
"event_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"event": "ORDER_PAYMENT_STATUS_CHANGED",
"occurred_at": "2024-01-15T10:30:00Z",
"data": {
"order_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"customer_id": "019b21da-0a3e-7c41-9f2b-5e8d1c7a4b60",
"new_payment_status": "PAYMENT_PAID"
}
}
Пример payload для ORDER_DELIVERY_STATUS_CHANGED:
{
"event_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"event": "ORDER_DELIVERY_STATUS_CHANGED",
"occurred_at": "2024-01-15T10:30:00Z",
"data": {
"order_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"customer_id": "019b21da-0a3e-7c41-9f2b-5e8d1c7a4b60",
"chunk_id": 1,
"new_delivery_status": "DELIVERED"
}
}
Пример payload для CUSTOMER_CHANGED:
{
"event_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"event": "CUSTOMER_CHANGED",
"occurred_at": "2024-01-15T10:30:00Z",
"data": {
"customer_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9"
}
}
Пример payload для CART_UPDATED:
{
"event_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9",
"event": "CART_UPDATED",
"occurred_at": "2024-01-15T10:30:00Z",
"data": {
"customer_id": "019b21d9-c5d9-777d-80bd-d67c664bc6d9"
}
}
Верификация подписи
Каждый запрос содержит заголовок X-Webhook-Signature — HMAC-SHA256 от тела запроса, вычисленный с помощью поля secret вебхука.
Используйте его для проверки подлинности входящего запроса:
Запрос
expected = HMAC-SHA256(key=secret, data=request_body)
valid = (X-Webhook-Signature == hex(expected))
Повторные попытки доставки
Доставка работает по принципу at-least-once: одно и то же событие может прийти повторно с тем же event_id.
Система повторяет доставку с экспоненциальной задержкой при следующих ответах сервера:
5xx— серверные ошибки.408 Request Timeout,429 Too Many Requests.401 Unauthorized,403 Forbidden(например, во время ротации секрета на стороне приемника).404 Not Found(например, во время деплоя приемника).3xx— редиректы не выполняются, доставка повторяется на исходный URL.- Сетевые ошибки и таймаут запроса (10 секунд).
Остальные ответы 4xx (включая 410 Gone) считаются окончательным отказом — доставка не повторяется.
Каждая подписка получает событие независимо. Если один из вебхуков не отвечает, повторы поступают только ему, остальные подписки получают событие один раз. Если вебхук удалили, отключили или отписали от события, повторы прекращаются.
| Попытка | Задержка перед попыткой |
|---|---|
| 1 | — |
| 2 | 5 сек. |
| 3 | 10 сек. |
| 4 | 20 сек. |
| 5 | 40 сек. |
| 6 | ~1,3 мин. |
| 7 | ~3 мин. |
| 8 | ~5 мин. |
| 9 | ~11 мин. |
| 10 | ~21 мин. |
| 11 | ~43 мин. |
| 12 и далее | 1 ч. |
Задержки указаны без случайного разброса: фактическая задержка отличается от табличной до ±20% и не превышает максимальный интервал.
Если приемник на 429 или 503 вернул заголовок Retry-After, следующая попытка повторится не раньше
указанного времени, но не позже максимального интервала.
Параметры
- Начальный интервал — 5 секунд.
- Коэффициент — 2.
- Максимальный интервал — 1 час.
- Случайный разброс задержки — ±20%.
- Общее окно — 72 часа с момента постановки события в доставку. После окончания окна событие считается недоставленным и больше не отправляется.
Для CART_UPDATED общее окно — 1 час, максимальный интервал — 10 минут.
Порядок доставки
Доставка вебхуков не гарантируется в хронологическом порядке: событие, которое произошло позже, может быть доставлено раньше.
Чтобы восстановить правильную хронологию, используйте поле occurred_at из payload
Активация вебхука
После создания вебхук находится в статусе INACTIVE и не отправляет уведомления.
Чтобы активировать вебхук:
- Вызовите
POST /v1/webhooks/{webhook_id}/validate?activate=true. - Система отправит POST-запрос на ваш URL с телом —
{"event_id": "...", "event": "WEBHOOK_VALIDATE", "occurred_at": "..."}. - Ваш сервер должен вернуть HTTP 2xx с телом:
{ "message": "validated_store_{store_id}" }{store_id}— идентификатор вашего магазина (доступен черезGET /v1/store).
- При успешной проверке вебхук автоматически изменит статус на
ACTIVE. - При изменении URL вебхука он переходит в статус
INACTIVE, после чего требуется повторная валидация.