> ## 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.

# Ошибки

API использует стандартизированный формат ответов об ошибках. Все ошибки возвращаются в формате JSON с единой структурой.

## Структура ответа об ошибке

Все ошибки возвращаются в следующем формате:

```json theme={null}
{
  "code": "ErrorCode",
  "message": "Человекочитаемое описание ошибки",
  "details": {
    // Дополнительная информация об ошибке (опционально)
  },
  "request_id": "xxxx"
}
```

### Поля ответа

* **`code`** (обязательное): Машиночитаемый код ошибки. Используйте его для программной обработки ошибок.
* **`message`** (обязательное): Человекочитаемое описание ошибки на языке, указанном в заголовке `Accept-Language` или языке по умолчанию.
* **`details`** (опциональное): Дополнительная информация об ошибке. Структура зависит от типа ошибки.
* **`request_id`** (опциональное): Эхо заголовка `X-Request-ID`, переданного в запросе. Используется для трассировки запросов.

## Коды ошибок

### Ошибки аутентификации и авторизации

#### 401 Unauthorized

Ошибка аутентификации. Возвращается в следующих случаях:

* **Отсутствует или недействителен клиентский сертификат (mTLS)**: Запрос не содержит валидный клиентский сертификат или сертификат не прошел проверку.
* **Отсутствует или недействителен Bearer токен**: Заголовок `Authorization` отсутствует, имеет неверный формат, или токен истек/недействителен.
* **Неверный формат токена**: Токен не является валидным JWT или имеет неверную структуру.

**Пример ответа (отсутствует клиентский сертификат):**

```json theme={null}
{
  "code": "Unauthorized",
  "message": "Требуется клиентский сертификат для mTLS аутентификации",
  "request_id": "f2c8a9f6-1234-5678-9abc-def012345678"
}
```

**Пример ответа (отсутствует Bearer токен):**

```json theme={null}
{
  "code": "Unauthorized",
  "message": "Требуется Bearer токен в заголовке Authorization",
  "request_id": "f2c8a9f6-1234-5678-9abc-def012345678"
}
```

**Пример ответа (недействительный токен):**

```json theme={null}
{
  "code": "Unauthorized",
  "message": "Токен истек или недействителен",
  "request_id": "f2c8a9f6-1234-5678-9abc-def012345678"
}
```

#### 403 Forbidden

Недостаточно прав для выполнения операции. Возвращается в следующих случаях:

* **Отсутствует необходимый scope в токене**: Токен валиден, но не содержит требуемый scope для данной операции.
* **Неверный audience (aud) в токене**: Поле `aud` в JWT не соответствует ожидаемому значению для данного API.

**Пример ответа (отсутствует scope):**

```json theme={null}
{
  "code": "Forbidden",
  "message": "Недостаточно прав для операции (требуется scope: booking.lounges)",
  "details": {
    "required_scope": "booking.lounges",
    "provided_scopes": ["catalog.lounges"]
  },
  "request_id": "f2c8a9f6-1234-5678-9abc-def012345678"
}
```

**Пример ответа (неверный audience):**

```json theme={null}
{
  "code": "Forbidden",
  "message": "Токен выдан для другого API (неверный audience)",
  "details": {
    "expected_aud": "https://api.every.ru/business-lounges",
    "provided_aud": "https://api.every.ru/other-service"
  },
  "request_id": "f2c8a9f6-1234-5678-9abc-def012345678"
}
```

### Ошибки валидации и бизнес-логики

#### 400 Bad Request

Некорректный запрос. Возвращается при ошибках валидации входных данных.

**Код ошибки:** `ValidationError`

**Пример ответа:**

```json theme={null}
{
  "code": "ValidationError",
  "message": "Некорректные параметры запроса",
  "details": {
    "field": "guests_count",
    "reason": "Количество гостей не может быть больше 10 человек"
  },
  "request_id": "xxxx"
}
```

#### 404 Not Found

Ресурс не найден. Возвращается в следующих случаях:

**Код ошибки:** `CatalogResourceNotFound`

Ресурс каталога (бизнес-зал или фаст-трек) не найден.

**Пример ответа:**

```json theme={null}
{
  "code": "CatalogResourceNotFound",
  "message": "Ресурс не найден",
  "request_id": "xxxx"
}
```

**Код ошибки:** `BookingNotFound`

Бронирование не найдено.

**Пример ответа:**

```json theme={null}
{
  "code": "BookingNotFound",
  "message": "Бронирование не найдено",
  "request_id": "xxxx"
}
```

#### 409 Conflict

Конфликт состояния операции. Возвращается в следующих случаях:

**Код ошибки:** `IdempotencyConflict`

Конфликт идемпотентности. Возвращается, когда запрос с существующим `Idempotency-Key` содержит тело запроса, отличающееся от сохранённого при первом использовании ключа.

**Пример ответа:**

```json theme={null}
{
  "code": "IdempotencyConflict",
  "message": "Idempotency Key используется с другими параметрами",
  "request_id": "xxxx"
}
```

**Код ошибки:** `BookingAlreadyConfirmed`

Попытка подтвердить уже подтверждённую бронь.

**Пример ответа:**

```json theme={null}
{
  "code": "BookingAlreadyConfirmed",
  "message": "Бронь уже подтверждена",
  "request_id": "xxxx"
}
```

**Код ошибки:** `BookingAlreadyCanceled`

Попытка отменить уже отменённую бронь.

**Пример ответа:**

```json theme={null}
{
  "code": "BookingAlreadyCanceled",
  "message": "Бронь уже отменена",
  "request_id": "xxxx"
}
```

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

#### 202 Accepted (PassNotReady)

Бронь находится в обработке, данные для прохода недоступны. Это не ошибка, а индикатор того, что данные ещё не готовы.

**Код ошибки:** `PassNotReady`

**Заголовки ответа:**

* `Location`: URL ресурса для поллинга статуса (тот же endpoint `/pass`)
* `Retry-After`: Рекомендуемая задержка перед повтором в секундах

**Пример ответа:**

```json theme={null}
{
  "code": "PassNotReady"
}
```

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

* Используйте заголовок `Retry-After` для определения интервала поллинга
* Повторяйте запрос к тому же endpoint `/pass` до получения успешного ответа или ошибки

#### 500 Internal Server Error

Внутренняя ошибка сервиса. Возвращается при неожиданных ошибках на стороне сервера.

**Код ошибки:** `InternalError`

**Пример ответа:**

```json theme={null}
{
  "code": "InternalError",
  "message": "Внутренняя ошибка сервиса",
  "request_id": "xxxx"
}
```

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

* Не повторяйте запрос немедленно — это может быть временная проблема
* Если ошибка повторяется, обратитесь в поддержку с `request_id`

#### 503 Service Unavailable

Сервис временно недоступен. Возвращается при временной недоступности сервиса (например, при техническом обслуживании).

**Код ошибки:** `ServiceUnavailable`

**Заголовки ответа:**

* `Retry-After`: Рекомендуемая задержка перед повтором в секундах

**Пример ответа:**

```json theme={null}
{
  "code": "ServiceUnavailable",
  "message": "Сервис временно недоступен",
  "request_id": "xxxx"
}
```

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

* Используйте экспоненциальную задержку между повторными попытками
* Учитывайте заголовок `Retry-After` при планировании повторных запросов

### Успешные ответы

#### 304 Not Modified

Ресурс не был изменен с момента последнего запроса. Возвращается при использовании условных запросов с заголовками `If-None-Match` или `If-Modified-Since`.

**Особенности:**

* Тело ответа отсутствует (экономия трафика)
* Возвращаются заголовки `ETag` и `Last-Modified`

Это не ошибка, а оптимизация для уменьшения трафика при повторных запросах к каталогам.

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

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

1. **Используйте код ошибки для логики**: Проверяйте поле `code` для программной обработки ошибок, а не HTTP статус код или сообщение.

2. **Сохраняйте request\_id**: Всегда логируйте `request_id` из ответа об ошибке. Это поможет при обращении в поддержку.

3. **Обрабатывайте детали ошибки**: Поле `details` может содержать полезную информацию для исправления проблемы (например, какие поля не прошли валидацию).

4. **Повторные запросы**:
   * Для `503 Service Unavailable`: используйте экспоненциальную задержку и учитывайте `Retry-After`
   * Для `202 PassNotReady`: повторяйте запрос с интервалом, указанным в `Retry-After`
   * Для `500 Internal Error`: не повторяйте немедленно, это может быть постоянная проблема

5. **Ошибки аутентификации**: При получении `401 Unauthorized` проверьте:
   * Наличие и валидность клиентского сертификата (mTLS)
   * Наличие и валидность Bearer токена
   * Срок действия токена (токены действительны 1 час)

6. **Ошибки авторизации**: При получении `403 Forbidden` проверьте:
   * Наличие необходимых scope в токене
   * Правильность audience (aud) в JWT токене

## Таблица кодов ошибок

| HTTP код | Код ошибки                | Описание                         |
| -------- | ------------------------- | -------------------------------- |
| 400      | `ValidationError`         | Ошибка валидации входных данных  |
| 401      | `Unauthorized`            | Ошибка аутентификации            |
| 403      | `Forbidden`               | Недостаточно прав для операции   |
| 404      | `CatalogResourceNotFound` | Ресурс каталога не найден        |
| 404      | `BookingNotFound`         | Бронирование не найдено          |
| 409      | `IdempotencyConflict`     | Конфликт идемпотентности         |
| 409      | `BookingAlreadyConfirmed` | Бронь уже подтверждена           |
| 409      | `BookingAlreadyCanceled`  | Бронь уже отменена               |
| 500      | `InternalError`           | Внутренняя ошибка сервиса        |
| 503      | `ServiceUnavailable`      | Сервис временно недоступен       |
| 202      | `PassNotReady`            | Данные для прохода ещё не готовы |
