Продажа билетов

Продажа — три шага: бронь, заказ, оплата. Права: orders:write на запись, orders:read на чтение.

1. Бронь мест

POST https://api.ctickets.ru/v1/reservations
Idempotency-Key: rsv-2026-08-03-0001

{
  "event_id": 145,
  "seats": [
    { "zone_id": "zone-1", "seat_id": "zone-1-1-1" },
    { "zone_id": "zone-1", "seat_id": "zone-1-1-2" }
  ],
  "ttl_minutes": 15
}
{
  "data": {
    "id": "rsv_01kz47mjrk0498wmtheejfkkmp",
    "status": "reserved",
    "expires_at": "2026-08-03T19:50:00+03:00",
    "seats": [{
      "zone_id": "zone-1", "seat_id": "zone-1-1-1",
      "row": "1", "number": "1",
      "label": "1 Сектор, ряд 1, место 1",
      "ticket_category_id": 423,
      "price": { "amount": 300000, "currency": "RUB" }
    }],
    "total": { "amount": 600000, "currency": "RUB" }
  }
}

Бронь хранится у нас, а не у вас. Иначе при нескольких витринах каждая считала бы место свободным и одно кресло продалось бы дважды. Если место успели занять — 409 seat_taken со списком unavailable_seats: обновите занятость и предложите покупателю другие места.

Состав брони меняется целиком: PATCH /v1/reservations/{id} с полным новым списком мест — вам не нужно считать разницу.

2. Заказ

POST https://api.ctickets.ru/v1/orders
Idempotency-Key: order-2026-08-03-0001

{
  "event_id": 145,
  "reservation_id": "rsv_01kz47mjrk0498wmtheejfkkmp",
  "customer": {
    "email": "buyer@example.com",
    "first_name": "Иван",
    "last_name": "Петров",
    "phone": "+79000000001"
  },
  "payment": "gateway"
}

Событие без схемы (без выбора мест) заказывается составом категорий:

"items": [{ "ticket_category_id": 423, "quantity": 2 }]

3. Оплата — две модели

Платим мы

"payment": "gateway" — в ответе придёт payment_url. Ведите покупателя туда; после оплаты мы сами выпустим билеты и отправим их на почту.

Платите вы

"payment": "external" — деньги принимаете вы, расчёты с покупателем остаются на вашей стороне. Как только платёж прошёл, подтверждаете:

POST https://api.ctickets.ru/v1/orders/7809/confirm
Idempotency-Key: confirm-7809

{ "external_payment_id": "pay-test-001", "paid_amount": 600000 }

Если paid_amount не совпадёт с суммой заказа — 422 amount_mismatch. Повторный confirm безопасен: вернётся тот же оплаченный заказ.

4. Билеты

GET https://api.ctickets.ru/v1/orders/7809/tickets
{
  "data": [{
    "id": 14906,
    "number": "TKT-20260803-DRUNGVWP",
    "barcode": "337069260809",
    "status": "active",
    "seat": { "zone_id": "zone-1", "seat_id": "zone-1-1-1", "label": "1 Сектор, ряд 1, место 1" },
    "price": { "amount": 300000, "currency": "RUB" },
    "order_url": "https://ctickets.ru/order/7809?access_token=..."
  }]
}

order_url — публичная ссылка на заказ: по ней покупатель откроет и скачает все билеты без авторизации.

Отмена и возврат

POST https://api.ctickets.ru/v1/orders/7809/refund
Idempotency-Key: refund-7809-1

{ "ticket_ids": [14906], "reason": "Покупатель вернул один билет" }

Деньги возвращает та сторона, что их приняла. В ответе поле money_returned_by: gateway — вернули мы через платёжный шлюз; external — платёж принимали вы, билеты мы погасили, деньги возвращаете сами.

Сервисный сбор

Сервисный сбор платформы уже учтён в суммах заказа. Если у вас есть собственная наценка — это ваши расчёты с покупателем, в API она не передаётся.

Вопросы по интеграции — api@ctickets.ru. Ключи и журнал запросов — в кабинете организатора, раздел «API и интеграции».