EN
Разделы документации

Места в зале

Билеты на конкретные места: тариф с местами, схема зала файлом CSV и заказ места по его подписи или вашему идентификатору.

Место всегда принадлежит одному тарифу, то есть ценовой категории. В одном событии можно смешивать тарифы с местами и тарифы с квотой: например, партер по местам и танцпол без мест. Одно место продаётся один раз, даже если двое покупают его в одну секунду.

Как завести событие с местами

  1. Создайте событие с тарифом "seated": true. Квоту такому тарифу не передают: она равна числу его мест.
  2. Загрузите места файлом CSV: POST /v1/events/{id}/seats. Сначала файл можно проверить с ?dry_run=1.
  3. Опубликуйте событие. Тариф с местами без загруженных мест опубликовать нельзя.

Места меняются только у черновика. Загрузка заменяет все места события целиком.

Формат CSV

csv

sector,row,number,label,external_id,tariff
Партер,1,1,П-1-1,hall-0001,parter
Партер,1,2,,hall-0002,parter
"Балкон, левая сторона",1,1,Б-1-1,hall-0101,balcony
СтолбецОбязательноОписание
sectorдаСектор, до 50 символов
rowдаРяд, до 20 символов
numberдаНомер места, до 20 символов
labelнетПодпись места, уникальна в событии, до 100 символов. Пусто: sector-row-number, во второй строке примера Партер-1-2
external_idнетВаш идентификатор места, например из схемы зала. Уникален в событии и не совпадает ни с одной подписью
tariffесли тарифов с местами несколькоКод или название тарифа с местами
  • Первая строка — заголовок. Регистр и пробелы вокруг названий не важны, порядок столбцов любой. Другой столбец — ошибка.
  • Разделитель , или ; (Excel с русскими настройками сохраняет через ;). Кавычки по RFC 4180, BOM и переводы строк Windows допускаются.
  • Кодировка только UTF-8. В Excel сохраняйте как «CSV UTF-8».
  • Пустые строки пропускаются. Управляющие символы внутри значений не допускаются.
  • Порядок строк — порядок мест в зале: в нём места отдаются в списке и в остатках.
  • До 50 000 мест и 5 МБ на файл.

Загрузить места

POST/v1/events/{id}/seats

Тело запроса — сам файл, Content-Type: text/csv. Файл принимается целиком или не принимается совсем. ?dry_run=1 проверяет и считает места, ничего не записывая.

Запрос

curl "https://api.budu.events/v1/events/0193e0b2-4a7c-7d10-9e3f-2c5a8b1d4e60/seats?dry_run=1" \
  -H "Authorization: Bearer $BUDU_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @hall.csv

Ответ 200

{
  "total": 3,
  "per_tariff": [
    {"tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c73", "count": 2},
    {"tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c74", "count": 1}
  ],
  "errors": [],
  "sample": [
    {
      "id": "0193e0b3-0a11-7f00-8d2b-41c6e9a7b001",
      "tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c73",
      "sector": "Партер",
      "row": "1",
      "number": "1",
      "label": "П-1-1",
      "external_id": "hall-0001",
      "position": 1
    }
  ]
}

sample — первые 20 мест для предпросмотра. Если в файле есть ошибки, ответ будет 400 invalid_request, ничего не запишется, а ошибки окажутся в details.errors:

Ответ 400

{
  "error": {
    "code": "invalid_request",
    "message": "В файле мест есть ошибки — места не загружены",
    "details": {
      "errors": [
        {"line": 3, "message": "Место «П-1-1» повторяется: строки 2 и 3"}
      ]
    }
  }
}

line — номер строки файла, заголовок — строка 1. line: 0 относится к файлу целиком. В ответе до 100 ошибок.

Idempotency-Key здесь не нужен: повтор того же файла даёт тот же результат. После публикации загрузка отвечает 400 «Места можно загрузить только до публикации».

Список мест

GET/v1/events/{id}/seats

ПараметрОписание
limitМест на странице, от 1 до 5 000, по умолчанию 1 000
afterid последнего места предыдущей страницы
sectorТолько этот сектор

Запрос

curl "https://api.budu.events/v1/events/0193e0b2-4a7c-7d10-9e3f-2c5a8b1d4e60/seats?limit=2" \
  -H "Authorization: Bearer $BUDU_KEY"

Ответ 200

{
  "seats": [
    {
      "id": "0193e0b3-0a11-7f00-8d2b-41c6e9a7b001",
      "tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c73",
      "sector": "Партер",
      "row": "1",
      "number": "1",
      "label": "П-1-1",
      "external_id": "hall-0001",
      "position": 1
    },
    {
      "id": "0193e0b3-0a11-7f00-8d2b-41c6e9a7b002",
      "tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c73",
      "sector": "Партер",
      "row": "1",
      "number": "2",
      "label": "Партер-1-2",
      "external_id": "hall-0002",
      "position": 2
    }
  ],
  "last": false,
  "sectors": ["Партер", "Балкон, левая сторона"]
}

Места идут в порядке файла. Следующая страница: after=<id последнего места>, пока last не станет true. sectors приходит только на первой странице.

Состояния мест

GET /v1/events/{id}/availability?seats=1 добавляет к остаткам страницу состояний мест: seats: [{seat_id, tariff_id, sector, label, state}] и seats_last. Страницы листаются так же, параметрами seats_after и seats_limit.

stateЧто значит
freeСвободно
heldВ резерве у заказа. Освободится, если резерв отменят или он истечёт
soldПродано. Снова станет free, если билет отменят с возвратом в продажу

Заказ места

В POST /v1/orders и POST /v1/reservations позиция с местом выглядит как {"seat": "<ссылка>"} вместо {"tariff_id", "qty"}:

json

{
  "event_id": "0193e0b2-4a7c-7d10-9e3f-2c5a8b1d4e60",
  "items": [
    {"seat": "П-1-1"},
    {"seat": "hall-0002"},
    {"tariff_id": "0193e0b2-4a7d-7a21-8c44-6e2f9a0b3c71", "qty": 2}
  ],
  "buyer": {
    "email": "anna@example.ru",
    "first_name": "Анна",
    "last_name": "Петрова"
  }
}
  • Ссылка на место — его id, external_id или label. Мы проверяем в этом порядке.
  • qty у места 0 или 1. tariff_id можно не указывать, а если указан, он должен совпадать с тарифом места.
  • Тариф с местами нельзя заказать количеством: 400 «Для этого тарифа выберите места».
  • Место считается за один билет в лимите 20 на заказ и в per_order_limit тарифа.
  • В заказе и билете место приходит объектом seat: {id, sector, row, number, label}. Гость видит «Сектор · Ряд · Место» на билете, в письме и в календаре.

Ошибки: 409 seat_taken, если место в резерве у другого заказа или продано (details.seat_id, details.seat). 404 not_found, если места нет в событии (details.seat). 409 event_not_on_sale с «Продажа мест ещё не открыта», если после публикации прошло несколько секунд и места ещё загружаются в продажу.