---
metadata:
  - name: generator
    content: Diplodoc Platform v5.70.0
alternate:
  - https://yandex.ru/dev/kit/ru/openapi/Vebhuki/index.md
  - href: https://yandex.ru/dev/kit/ru/openapi/Vebhuki/index.md
    type: text/markdown
    title: Markdown version
  - href: https://yandex.ru/dev/kit/ru/llms.txt?revision=r22093267
    rel: describedby
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.ru/dev/kit/ru/llms.txt?revision=r22093267

# Вебхуки

<!-- markdownlint-disable-file -->

Управление вебхуками магазина.

## Структура 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`:

```json
{
  "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`:

```json
{
  "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`:

```json
{
  "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`:

```json
{
  "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`:

```json
{
  "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` вебхука.
Используйте его для проверки подлинности входящего запроса:

{% cut "Запрос" %}

```
expected = HMAC-SHA256(key=secret, data=request_body)
valid = (X-Webhook-Signature == hex(expected))
```

{% endcut %}

## Повторные попытки доставки

Доставка работает по принципу 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`, следующая попытка повторится не раньше
указанного времени, но не позже максимального интервала.

{% cut "Параметры" %}

* Начальный интервал — 5 секунд.
* Коэффициент — 2.
* Максимальный интервал — 1 час.
* Случайный разброс задержки — ±20%.
* Общее окно — 72 часа с момента постановки события в доставку.
После окончания окна событие считается недоставленным и больше не отправляется.

Для `CART_UPDATED` общее окно — 1 час, максимальный интервал — 10 минут.

{% endcut %}

## Порядок доставки

Доставка вебхуков не гарантируется в хронологическом порядке: событие, которое произошло позже, может быть доставлено раньше.
Чтобы восстановить правильную хронологию, используйте поле `occurred_at` из payload

## Активация вебхука

После создания вебхук находится в статусе `INACTIVE` и не отправляет уведомления.

Чтобы активировать вебхук:

1. Вызовите `POST /v1/webhooks/{webhook_id}/validate?activate=true`.
2. Система отправит POST-запрос на ваш URL с телом — `{"event_id": "...", "event": "WEBHOOK_VALIDATE", "occurred_at": "..."}`.
3. Ваш сервер должен вернуть HTTP 2xx с телом:
   ```json
   { "message": "validated_store_{store_id}" }
   ```
     * `{store_id}` — идентификатор вашего магазина (доступен через `GET /v1/store`).
4. При успешной проверке вебхук автоматически изменит статус на `ACTIVE`.
5. При изменении URL вебхука он переходит в статус `INACTIVE`, после чего требуется повторная валидация.

## Endpoints

- [Получение списка вебхуков](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/GetWebhooks.md)
- [Создание вебхука](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/CreateWebhook.md)
- [Валидация вебхука](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/ValidateWebhook.md)
- [Получение вебхука по уникальному идентификатору](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/GetWebhookById.md)
- [Удаление вебхука](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/DeleteWebhook.md)
- [Обновление вебхука](https://yandex.ru/dev/kit/ru/openapi/Vebhuki/UpdateWebhook.md)
