# Ключи и запросы

Как передать ключ, чем тестовый ключ отличается от боевого и в каком виде API принимает и отдаёт данные.

## Ключ API {#keys}

Каждый запрос несёт ключ организации в заголовке:

```http
Authorization: Bearer bt_live_…
```

| Префикс | Режим | Что видит ключ |
|---|---|---|
| `bt_test_` | тестовый | только тестовые события, заказы, билеты и устройства |
| `bt_live_` | боевой | только боевые |

Ключи создаёт и отзывает владелец организации в кабинете, раздел **интеграция → ключи API**. Ключ работает в том режиме, в котором был открыт кабинет при его создании. Полный ключ показывают один раз. Мы храним только хэш, поэтому потерянный ключ не восстановить: отзовите его и создайте новый.

- Отозванный ключ перестаёт работать в течение 5 секунд.
- Ключ приостановленной организации не работает.
- Без ключа, с неверным или отозванным ключом ответ будет `401 unauthorized`.

> Ключ открывает все события и билеты организации в своём режиме. Держите его на сервере. В коде страницы, мобильном приложении или публичном репозитории ему не место.

## Адрес {#host}

Базовый адрес API: `https://api.budu.events/v1`. Запросы принимаются только по HTTPS.

## Организация и режим {#scope}

Организацию и режим определяет ключ. Поля `org_id` и `livemode` в теле запроса ни на что не влияют. Чужое событие, заказ или билет, а также объект другого режима выглядят как несуществующие: `404 not_found`.

## Что можно по ключу {#available}

| Раздел | Что делает |
|---|---|
| [События](https://budu.events/docs/events/) | создать, изменить, опубликовать, остатки, обложка |
| [Места в зале](https://budu.events/docs/seats/) | загрузить схему мест, список мест |
| [Заказы](https://budu.events/docs/orders/) | заказ после оплаты, резерв на время оплаты |
| [Билеты](https://budu.events/docs/tickets/) | найти, отменить, перевыпустить, отправить письмо ещё раз, выгрузить |
| [Выдача без оплаты](https://budu.events/docs/issue/) | выдать билеты вручную, загрузить список гостей |
| [Контролёры на входе](https://budu.events/docs/devices/) | подключить телефон контролёра, отчёт о проходах |

Ключи API, брендинг, тестовые адресаты, журнал действий и живые цифры события доступны только в кабинете. Ключ на такие запросы получает `403 forbidden` с `details.reason: "session_only"`.

## Формат данных {#format}

- Тело запроса — JSON в UTF-8, до 1 МБ. Файлы (места, список гостей, обложка) идут телом запроса как есть, со своим `Content-Type`.
- Имена полей в `snake_case`. Неизвестное поле в теле запроса даёт `400 invalid_request`: опечатка в имени поля не пройдёт молча. Исключение — устройства (`POST /v1/devices/invites`, `PATCH /v1/devices/{id}`): там лишние поля игнорируются.
- Ответ содержит все поля объекта, даже пустые: строка `""`, число `0`, список `[]`, вложенный объект `null`.
- Идентификаторы — UUID строкой: `"0193e0b2-4a7c-7d10-9e3f-2c5a8b1d4e60"`.
- Время — строка RFC 3339. В ответах всегда UTC: `"2026-12-12T16:00:00Z"`. В запросах можно указать смещение: `"2026-12-12T19:00:00+03:00"`.
- Поля `*_ms` — миллисекунды Unix. `"0"` значит «не было»: `"checked_in_at_ms": "0"` у билета, который не проходил.
- 64-битные числа (`price_minor` и все `*_ms`) в ответах приходят **строкой**: `"price_minor": "250000"`. Так protobuf записывает их в JSON. В запросах подойдёт и число, и строка.
- Деньги — в минимальных единицах валюты: `250000` копеек — это 2 500 ₽. Валюта — трёхбуквенный код, по умолчанию `RUB`.

## Заголовки {#headers}

| Заголовок | Где | Зачем |
|---|---|---|
| `Authorization` | запрос | `Bearer` и ключ API |
| `Idempotency-Key` | запрос, `POST` и `DELETE` | безопасный повтор, см. [идемпотентность](https://budu.events/docs/idempotency/) |
| `Content-Type` | запрос с телом | `application/json` для JSON, `text/csv` для мест и гостей, `image/jpeg`, `image/png` или `image/webp` для обложки |
| `X-Request-Id` | ответ | номер запроса в наших логах. Назовите его, если пишете нам о проблеме |
| `Idempotent-Replayed` | ответ | `true`, если это сохранённый ответ на повтор |
| `Retry-After` | ответ `429` | через сколько секунд повторить |
