> ## Documentation Index
> Fetch the complete documentation index at: https://developer.every.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Работа с веб-хуками

> Получение информации о событиях через веб хуки.

## Настройка webhooks

У аккаунта может быть **не более одной** webhook-подписки. События **не выбираются** при создании: после подписки доставляются **все** поддерживаемые типы уведомлений. Управление — отдельными command-эндпоинтами (создание, смена URL, ротация секрета, отключение, включение, удаление).

### Создание подписки

`POST /v2/b2b/webhooks` — в теле обязательны **`url`** и **`secret`** (HMAC-SHA256, 16–256 символов). Повторное создание при уже существующей подписке даёт **409**.

```bash theme={null}
curl -X POST https://b2b.every.ru/api/v2/b2b/webhooks \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "url": "https://partner.example.com/webhooks",
    "secret": "your-secret-key-here"
  }'
```

**Пример ответа (201):**

```json theme={null}
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "url": "https://partner.example.com/webhooks",
  "active": true,
  "created_at": "2025-11-08T06:00:00Z",
  "updated_at": "2025-11-08T06:00:00Z"
}
```

### Список подписок

`GET /v2/b2b/webhooks` — в ответе **0 или 1** элемент в `data` (ограничение «одна подписка на аккаунт»).

```bash theme={null}
curl -X GET https://b2b.every.ru/api/v2/b2b/webhooks \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>'
```

**Пример, если подписка есть:**

```json theme={null}
{
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "url": "https://partner.example.com/webhooks",
      "active": true,
      "created_at": "2025-11-08T06:00:00Z",
      "updated_at": "2025-11-08T06:00:00Z"
    }
  ],
  "pagination": {
    "count": 1,
    "offset": 0,
    "total": 1
  }
}
```

**Пример, если подписок нет:**

```json theme={null}
{
  "data": [],
  "pagination": {
    "count": 0,
    "offset": 0,
    "total": 0
  }
}
```

### Получение подписки

`GET /v2/b2b/webhooks/{webhookID}`

```bash theme={null}
curl -X GET https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000 \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>'
```

### Изменение URL

`POST /v2/b2b/webhooks/{webhookID}/change-url` — в теле **`url`**.

```bash theme={null}
curl -X POST https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000/change-url \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{"url": "https://partner.example.com/webhooks/new"}'
```

### Ротация секрета

`POST /v2/b2b/webhooks/{webhookID}/rotate-secret` — в теле **`secret`** (новый); опционально **`grace_period_seconds`** (по умолчанию 60, диапазон 60–2592000). Старый секрет остаётся валидным на время grace-периода.

```bash theme={null}
curl -X POST https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000/rotate-secret \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{"secret": "new-secret-key-here", "grace_period_seconds": 120}'
```

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

`POST /v2/b2b/webhooks/{webhookID}/disable` — тело опционально, можно передать **`reason`** для аудита.

```bash theme={null}
curl -X POST https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000/disable \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{"reason": "maintenance"}'
```

### Возобновление доставки

`POST /v2/b2b/webhooks/{webhookID}/enable`

```bash theme={null}
curl -X POST https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000/enable \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <TOKEN>'
```

### Удаление подписки

`DELETE /v2/b2b/webhooks/{webhookID}`

```bash theme={null}
curl -X DELETE https://b2b.every.ru/api/v2/b2b/webhooks/123e4567-e89b-12d3-a456-426614174000 \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --header 'Authorization: Bearer <TOKEN>'
```

После удаления уведомления больше не отправляются.

## Формат webhook-уведомлений

Все webhook-уведомления отправляются в формате JSON и содержат следующую структуру:

```json theme={null}
{
  "event": "booking.status.changed",
  "timestamp": "2025-11-08T06:00:00Z",
  "data": {
  }
}
```

### Поля уведомления

* **`event`** (обязательно): тип события:
  * `booking.status.changed` — изменение статуса бронирования
  * `pass.status.changed` — изменение статуса прохода
* **`timestamp`** (обязательно): время события в ISO 8601 (UTC).
* **`data`** (обязательно): данные события, структура зависит от типа.

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

### Проверка подлинности уведомлений

При создании подписки задаётся **`secret`**; при необходимости его меняют через **`rotate-secret`**. Уведомления подписываются **HMAC-SHA256**, значение передаётся в заголовке **`X-Webhook-Signature`**.

**Заголовок подписи:**

```
X-Webhook-Signature: sha256=abc123def456...
```

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

1. Получите значение заголовка `X-Webhook-Signature`
2. Извлеките подпись (часть после `sha256=`)
3. Вычислите HMAC-SHA256 от тела запроса (raw body) с использованием актуального секрета
4. Сравните вычисленную подпись с полученной

**Важно:**

* Всегда проверяйте подпись перед обработкой уведомления
* Используйте безопасное сравнение подписей (constant-time comparison)
* Храните секрет вне кода и репозитория

### Требования к endpoint

Ваш webhook endpoint должен:

* **Быть доступен по HTTPS**
* **Возвращать статус 200** при успешном приёме
* **Обрабатывать запросы быстро** (при необходимости — асинхронно после ответа 200)
* **Быть идемпотентным**: одно и то же уведомление может прийти повторно

## Обработка ошибок

### Ответы вашего endpoint

* **200 OK** — уведомление принято
* **400 / 500** — возможны повторные попытки доставки со стороны API

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

При ошибке или таймауте API может повторить отправку с экспоненциальной задержкой.

## Авторизация

Для вызовов API управления подписками нужен scope **`webhooks`** в Bearer-токене:

```bash theme={null}
curl -X POST https://auth.every.ru/oauth/v2/token \
  -u "client_id:client_secret" \
  -d "grant_type=client_credentials" \
  -d "scope=webhooks booking.lounges booking.fast_tracks"
```

Подробнее: [авторизация](./authorization.mdx).

## Ограничения

* Не более **одной** webhook-подписки на аккаунт
* Максимальный размер тела уведомления: **64 KB**
* Таймаут ожидания ответа от вашего endpoint: **30 секунд**

## Поддержка

1. Проверьте логи webhook endpoint
2. Убедитесь, что URL доступен по HTTPS и отвечает **200**
3. Проверьте подпись уведомлений
4. Обратитесь в поддержку с **`request_id`** из ответов API
