Booking Flow
Полный пример от поиска рейса до подтверждённого билета.
Шаги
- Поиск аэропортов
- Поиск маршрутов
- Поиск рейсов
- Получение fare price
- Создание брони
- Оплата
- E-ticket
Шаг 1. Аэропорты
curl -H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
"https://api.nurcore.kg/api/v1/schedules/airports?search=BSZ"Шаг 2. Маршруты
curl -H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
"https://api.nurcore.kg/api/v1/schedules/routes?origin=BSZ&destination=OSS"Шаг 3. Поиск рейсов
curl -H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
"https://api.nurcore.kg/api/v1/schedules/flights/?route_code=BSZ-OSS&flight_date=2026-05-10"Шаг 4. Fare price
curl -H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
"https://api.nurcore.kg/api/v1/fares/prices/?flight_id=$FLIGHT_ID&fare_class=economy"Ответ содержит fare_price_id, который нужен для создания брони.
Шаг 5. Создание брони
curl -X POST \
-H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
-H "Content-Type: application/json" \
-d '{
"flight_id": "'$FLIGHT_ID'",
"fare_price_id": "'$FARE_PRICE_ID'",
"passengers": [{
"first_name": "JOHN",
"last_name": "DOE",
"passenger_type": "adult",
"date_of_birth": "1990-01-15",
"gender": "male",
"nationality": "KGZ",
"document_type": "passport",
"document_number": "AN1234567"
}],
"contact_email": "user@example.com",
"contact_phone": "+996555000000"
}' \
"https://api.nurcore.kg/api/v1/bookings/"Response:
{
"id": "uuid",
"booking_reference": "ABC123",
"status": "pending",
"total_amount": 5000.00,
"currency": "KGS",
"expiry_date": "2026-04-28T12:15:00Z"
}PNR создан, у вас 15 минут на оплату.
Шаг 6. Оплата
Вариант A: с partner-баланса (только B2B)
curl -X POST \
-H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
"https://api.nurcore.kg/api/v1/bookings/$BOOKING_ID/pay-with-balance"Вариант B: внешний платёжный провайдер
curl -X POST \
-H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: consumer_app" \
-H "Content-Type: application/json" \
-d '{"amount": 5000.00, "currency": "KGS", "return_url": "https://your-site.com/result"}' \
"https://api.nurcore.kg/api/v1/bookings/$BOOKING_ID/initiate-payment"Откроется страница провайдера. После успеха NurCore автоматически переведёт бронь в CONFIRMED.
Шаг 7. E-ticket
После оплаты пассажир получает на email magic-link для просмотра брони и скачивания e-ticket.
curl -H "X-API-Key: $KEY" \
-H "X-Client-Id: $CLIENT_ID" \
-H "X-Client-Type: agency" \
-O \
"https://api.nurcore.kg/api/v1/bookings/$BOOKING_ID/eticket"Взрослый / ребёнок / младенец + туда-обратно (quote flow)
Разные типы пассажиров тарифицируются по разным правилам. Используйте Quote API (рекомендуемый путь) — он считает per-pax-type и round-trip за один запрос.
curl -X POST \
-H "X-API-Key: $KEY" -H "X-Client-Type: consumer_app" \
-H "Content-Type: application/json" \
-d '{
"origin": "BSZ", "destination": "OSS",
"departure_date": "2026-05-19",
"return_date": "2026-05-19",
"pax": [
{"type": "adult", "count": 1},
{"type": "child", "count": 1},
{"type": "infant", "count": 1}
],
"target_currency": "KGS"
}' \
"https://api.nurcore.kg/api/v1/fares/quote"Ответ (сокращённо):
{
"quote_id": "…",
"round_trip": true,
"segment_prices": ["6460.00", "6460.00"],
"net": "13320.00",
"line_items": [
{"description": "Туда: Adult × 1", "amount": "3800.00"},
{"description": "Туда: Child × 1", "amount": "2660.00"},
{"description": "Туда: Infant × 1 (free, lap infant)", "amount": "0.00"},
{"description": "Обратно: Adult × 1", "amount": "3800.00"},
{"description": "Обратно: Child × 1", "amount": "2660.00"},
{"description": "Обратно: Infant × 1 (free, lap infant)", "amount": "0.00"},
{"description": "VAT — НДС", "amount": "1278.72", "metadata": {"code": "VAT", "refundable": true, "jurisdiction": "KG"}},
{"description": "YQ — Топливный сбор", "amount": "2000.00", "metadata": {"code": "YQ", "refundable": true, "applies_to": "per_pax"}},
{"description": "AIRPORT_KG — Аэропортовый сбор", "amount": "400.00", "metadata": {"code": "AIRPORT_KG", "refundable": false, "applies_to": "per_segment"}},
{"description": "BOOK_FEE — Сервисный сбор", "amount": "100.00", "metadata": {"code": "BOOK_FEE", "refundable": false}}
]
}Ключевые правила:
adult≠child— у каждого свой FareRule/FarePrice (child обычно со скидкойdiscount_percentage).infant= 0 — lap infant без места (политика авиакомпании). Для PADISINS(infant with paid seat) использует adult-equivalent fare.- PADIS codes в
pax[].type:ADT/CHD/INF/INS/YTH/SRCпринимаются автоматически (см. Quote API → PADIS codes). - Tax v2 shape: каждый tax имеет
code(IATA или custom),refundable,applies_to,jurisdiction— для BSP reporting и refund flow (см. Quote API → Tax shape). - При создании брони передавайте
quote_id—netберётся из quote, не пересчитывается. Round-trip полностью покрыт quote (booking-service не добавляет return-доплату повторно приround_trip=true).
Round-trip в quote требует
origin+destination(неroute_id).
Выбор места в салоне (до создания брони)
Если тариф позволяет (fare_rule.seat_selection=true), пассажир может
выбрать конкретное место при бронировании, а не на регистрации.
# 1) Карта салона (доступна consumer-ключом без booking_id)
curl -H "X-API-Key: $KEY" \
"https://api.nurcore.kg/api/v1/checkin/flight/$FID/seat-map"
# 2) Цены зон (для отображения «+500 KGS за extra-legroom»)
curl -H "X-API-Key: $KEY" \
"https://api.nurcore.kg/api/v1/fares/seat-prices/for-booking?fare_rule_id=$RULE"
# 3) POST /bookings/ — место в passengers[i].seat_number
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{
"flight_id":"'$FID'", "fare_price_id":"'$FPID'", "quote_id":"'$QID'",
"passengers":[{"first_name":"JOHN","last_name":"DOE",
"passenger_type":"adult","date_of_birth":"1990-01-15",
"gender":"male","nationality":"KGZ",
"document_type":"passport","document_number":"AN1234567",
"seat_number":"12A"}],
"contact_email":"user@example.com"}' \
"https://api.nurcore.kg/api/v1/bookings/"Сервер сам определяет зону места по seat_map ВС, списывает seat_fee
из таблицы зон тарифа и добавляет в total_amount. Подробно — см.
раздел в Bookings API.
Возможные ошибки:
- 409 — место уже занято; обновите карту салона и выберите другое.
- 422 —
fare_rule.seat_selection=false(LIGHT-тариф) или неверный форматseat_number. Для предварительного выбора нужен Classic/Flex тариф.
Edge cases
- Бронь истекла (15 минут): статус
expired, места освобождены — нужно повторить с шага 3. - Места заняты: при concurrent создании броней — 409 Conflict, попробуйте другой рейс / класс.
- Максимум 9 PAX:
len(passengers) > 9→ 400 с детализированным сообщением.