API для разработчиков

API для разработчиков ROOM

Публичный REST API ROOM позволяет программно читать ваш каталог событий и продавать билеты по СБП с вашего сайта или сервера. Ключи создаются самостоятельно в бэкстейдже. Все ответы — JSON, суммы — в копейках (минорных единицах валюты).

Быстрый старт

1. Создайте ключ в разделе «API и вебхуки» бэкстейджа. Для боевых (live) ключей нужна верификация. Для тестов используйте sk_test — заказы создаются с mock-оплатой.

2. Сделайте первый запрос — список ваших событий:

curl
curl https://roombackstage.ru/api/public/v1/events \
  -H "Authorization: Bearer sk_test_ВАШ_КЛЮЧ"

Аутентификация

Ключ передаётся в заголовке Authorization: Bearer <ключ>. Существует два типа ключей:

  • sk_ — секретный, для сервера. Полный доступ (включая список заказов и персональные данные покупателей). Никогда не публикуйте его в браузере.
  • pk_ — публикуемый, для браузера. Работает только с разрешённых доменов (origin-binding) и не отдаёт персональные данные. Подходит для чекаута на лендинге.

Каждый ключ привязан к среде: test (mock-оплата, без реального СБП) или live (реальные платежи). Ключ видит и продаёт билеты только на события своего организатора.

Базовый URL и версия

https://roombackstage.ru/api/public/v1

Версия зафиксирована в пути (/v1). Ломающие изменения выйдут как /v2 — текущая версия продолжит работать.

Ошибки

Ошибки возвращаются со стабильным конвертом и подходящим HTTP-статусом:

json
{ "error": { "code": "insufficient_scope", "message": "...", "param": "scope" } }
  • 401 unauthorized — нет ключа, ключ невалиден/отозван/истёк.
  • 403 forbidden / insufficient_scope / origin_not_allowed — ключу не хватает прав или origin не разрешён.
  • 404 not_found — событие/заказ не принадлежит вашему ключу (намеренно не различаем «нет» и «чужое»).
  • 409 conflict / seat_conflict — место или тариф уже заняты.
  • 410 sales_closed — продажи по событию закрыты.
  • 422 — недопустимая операция (например, попытка бесплатного билета или не-СБП оплаты).
  • 429 rate_limited — превышен лимит. Смотрите заголовок Retry-After.
  • 502 payment_provider_error — провайдер оплаты временно недоступен, повторите.

Идемпотентность

Создание заказа (POST /orders) требует заголовок Idempotency-Key (без него — 400). Повтор с тем же ключом вернёт тот же заказ — защита от двойного списания при ретраях сети:

curl
curl https://roombackstage.ru/api/public/v1/orders \
  -H "Authorization: Bearer sk_live_ВАШ_КЛЮЧ" \
  -H "Idempotency-Key: order-2026-06-19-abc123" \
  -H "Content-Type: application/json" \
  -d '{ "tier_id": "...", "quantity": 2, "buyer": { "email": "fan@example.ru" } }'

Лимиты запросов

По умолчанию: чтение — ~600 запросов/мин на ключ, создание заказов/броней — ~60/мин. При превышении приходит 429 с заголовками Retry-After, X-RateLimit-Remaining, X-RateLimit-Reset.

Эндпоинты

Чтение каталога

  • GET /events — список опубликованных событий (cursor-пагинация).
  • GET /events/{id} — детали события, тарифы, лайнап.
  • GET /events/{id}/tiers — публичные тарифы.
  • GET /events/{id}/seating — схема зала и статус мест.
  • GET /events/{id}/availability — лёгкое наличие (счётчики + ценовой диапазон).

Коммерция

  • POST /orders/preview — предпросмотр цены и сбора без создания заказа.
  • POST /orders — создать заказ TICKET по СБП (вернёт QR + poll_token).
  • GET /orders/{id} — статус заказа (по poll_token или ключу).
  • POST /orders/{id}/check-status — свежая проверка статуса.
  • POST /seat-holds / DELETE /seat-holds — бронь мест для seating-событий.

Пример создания заказа из JavaScript:

javascript
const res = await fetch("https://roombackstage.ru/api/public/v1/orders", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_live_ВАШ_КЛЮЧ",
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    tier_id: "TIER_ID",
    quantity: 2,
    buyer: { email: "fan@example.ru" },
    return_url: "https://ваш-сайт.ru/spasibo", // опционально, только https
  }),
})
const order = await res.json()
// order.payment.qr_image / qr_payload — покажите СБП QR покупателю
// order.poll_token — опрашивайте статус GET /orders/{id} с этим токеном

Выбор билетов: tier_id (обычный тариф), либо seat_reservation_ids (места после POST /seat-holds), либо standing_items. Опрашивайте GET /orders/{id} с poll_token до status: "paid" — надёжный фолбэк к вебхукам.

Оплата и комиссия

Заказы через API оплачиваются только по СБП (рубли). Бесплатные билеты, Telegram Stars и крипта через API недоступны (422). Покупатель платит ровно цену из каталога — комиссию платформы платит организатор из своей выручки.

Ключи test используют mock-оплату: заказ создаётся, но реального СБП QR и списания нет — он сам гаснет через ~15 минут. Идеально для интеграционных тестов.

Вебхуки

ROOM может отправлять POST на ваш сервер при изменении статуса заказа. Настройте эндпоинт в разделе «API и вебхуки». Каталог событий (только билеты):

  • order.paid — заказ оплачен.
  • order.cancelled — заказ отменён/истёк.
  • order.refunded — по заказу прошёл возврат.

Тело — подписанный конверт:

json
{
  "id": "clz8a3k9b0001",      // cuid, стабилен между ретраями → дедуп
  "type": "order.paid",
  "api_version": "2026-06-01",
  "created_at": "2026-06-19T10:00:00.000Z",
  "data": { "order": { "id": "...", "status": "paid", "total_price": 150000, ... } }
}

Каждый запрос подписан заголовком ROOM-Signature: t=<ts>,v1=<hex>, где hex = HMAC-SHA256 от строки `${t}.${rawBody}` с вашим секретом whsec_. Всегда проверяйте подпись:

javascript
import crypto from "crypto"

function verify(rawBody, header, secret) {
  const [tPart, vPart] = header.split(",")
  const t = tPart.replace("t=", "")
  const v1 = vPart.replace("v1=", "")
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex")
  // сравнение постоянного времени
  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}

Доставка с ретраями (0с / 1м / 5м / 30м / 2ч / 5ч / 10ч / 24ч). После серии неудач эндпоинт автоматически отключается — мы пришлём уведомление. Дедуплицируйте по id конверта (он стабилен между повторами). Отвечайте 2xx для подтверждения; за деталями (включая персональные данные покупателя) обращайтесь к GET /orders/{id} с ключом sk_.