> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.voodoo.center/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.voodoo.center/_mcp/server.

# Помилки

## Конверт помилки

Помилки API повертають стандартний JSON-конверт із читабельним полем `detail`
та стабільним, машинозчитуваним `code`:

```json title="Відповідь із помилкою"
{
  "detail": "Insufficient balance",
  "code": "insufficient_balance"
}
```

Розгалужуйте обробку помилок за `code` (стабільним), а не за `detail` (текстом
для людини, який може змінюватися).

Ендпоінт **обміну токена** (`POST /api/v1/auth/token/client`) використовує
простішу форму для збоїв автентифікації: `{"error": "Invalid credentials"}` при
`401`. Кожен інший ендпоінт використовує конверт `detail` / `code`, наведений вище.

## Коди статусів

| HTTP  | `code`                 | Коли                                                                                                                                                                            |
| ----- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | `validation_error`     | Некоректне або відсутнє поле, невідомий/недоступний товар (зокрема відсутність у наявності на момент створення), дубльований `merchant_order_id` або кількість поза діапазоном. |
| `400` | `insufficient_balance` | Баланс вашого акаунта не покриває замовлення.                                                                                                                                   |
| `401` | `not_authenticated`    | Відсутній, недійсний або прострочений токен доступу. Повторно [обміняйте свій API-ключ](/authentication).                                                                       |
| `404` | `not_found`            | Замовлення не існує або не належить вашому акаунту.                                                                                                                             |
| `409` | `already_exists`       | Конфлікт з наявним ресурсом.                                                                                                                                                    |
| `5xx` | —                      | Помилка бекенду. Повторюйте з відстрочкою; використовуйте `merchant_order_id`, щоб повторні спроби залишалися ідемпотентними.                                                   |

### Приклади

```json title="400 — помилка валідації"
{ "detail": "Item is not available", "code": "validation_error" }
```

```json title="400 — недостатній баланс"
{ "detail": "Insufficient balance", "code": "insufficient_balance" }
```

```json title="401 — не автентифіковано"
{ "detail": "Authentication credentials were not provided.", "code": "not_authenticated" }
```

```json title="404 — не знайдено"
{ "detail": "Not found.", "code": "not_found" }
```

## Помилки під час створення проти асинхронних збоїв

Існує два різні види «збою», і вони проявляються в різних місцях:

* **Помилки під час створення (HTTP)** — запит **відхиляється**, і нічого не
  списується. Вони повертаються як `4xx`/`5xx` із конвертом помилки в момент,
  коли ви викликаєте `POST /api/v1/orders`. Приклад: товар, якого **немає в
  наявності на момент створення**, повертає `400 validation_error` («Item is not
  available»).

* **Асинхронні збої (термінальний статус)** — замовлення було **прийнято**
  (`201`, `status: "pending"`), і ваш баланс було списано, але виконання пізніше
  дало збій або було успішним лише частково. Це **не** HTTP-помилка. Натомість
  замовлення завершується термінальним `status` `failed` (з `error` /
  `error_message`, наприклад `OUT_OF_STOCK`, і повним `refund_amount`) або
  `partial` (з `refund_amount` за недоставлені одиниці). Ви дізнаєтеся про це зі
  свого [webhook](/webhooks) або `GET /api/v1/orders/{id}`.

Правило: якщо ви отримали `201`, замовлення існує та було списано — слідкуйте за
його `status`, а не за HTTP-відповіддю, щоб дізнатися результат. Якщо ви отримали
`4xx`, нічого не сталося, і ви можете безпечно виправити запит і повторити спробу.

## Безпечне повторення спроб

Завжди надсилайте унікальний `merchant_order_id` у `POST /api/v1/orders`. Він
унікальний у межах акаунта, тож якщо повторна спроба (після таймауту чи `5xx`)
використає те саме значення, ви випадково не розмістите дубльоване замовлення —
дублікат відхиляється з `400 validation_error`.

Виправляйте `401`, повторно обмінюючи свій API-ключ на свіжий токен.

Куди доставляються асинхронні результати `failed` / `partial`.