Ancillary Services (SSR)
Дополнительные услуги — багаж, питание, выбор места, помощь пассажирам.
NurCore поддерживает SSR (Special Service Requests, IATA Resolution 791) для дополнительных услуг сверх базового тарифа. Источник правды для SSR разнесён по двум сервисам:
| Сервис | Endpoint | Назначение |
|---|---|---|
| fare-service | /api/v1/fares/ssr-services/ | Глобальный справочник доступных SSR |
| fare-service | /api/v1/fares/ssr-availability/by-flight | Доступность для конкретного рейса с правилами |
| booking-service | /api/v1/bookings/services/categories | Список категорий для UI-фильтров |
| booking-service | POST /api/v1/bookings/ (поле offers) | Добавление SSR при создании броней |
Категории SSR
| Category | Label (ru) | Примеры кодов |
|---|---|---|
baggage | Багаж | XBAG (23кг), HBAG (32кг), SBAG (sports), PBAG (per kg) |
seat | Места | RQST, LEGR (extra legroom), NRBY (seats together), EXST (extra seat ×2) |
meal | Питание | VGML, VLML, MOML, KSML, DBML, GFML, CHML, BBML, SPML, MEAL |
assistance | Помощь пассажирам | WCHR, WCHS, WCHC, BLND, DEAF, MAAS, UMNR |
pet | Животные | PETC (в салоне), AVIH (в багажном) |
comfort | Комфорт | LOUG, BIKE, UPGR, FTRK (Fast Track / Priority Boarding) |
other | Прочие | SMSN (SMS уведомления), OTHS |
2026-06-01: SSR catalog приведён в соответствие с IATA Resolution 791. Деактивированы misused codes:
TKNE(это PNR field, не SMS),NSSB(obsolete since 2000s),INSR/CXLP(не SSR — отдельные продукты),SEAT(категория, не код),FPTV(renamed →FTRK). СемантикаEXSTисправлена — это полное доп.место (×2 места) для габаритного пассажира / cabin baggage, не extra legroom (для legroom теперьLEGR).
Advance booking time (IATA Recommended Practice 1701)
Некоторые SSR требуют запроса заранее — нужно подготовить оборудование, документы, hold-container. Если quote делается ближе к вылету → HTTP 400 с подсказкой обратиться в авиакомпанию.
| Код | Минимум до вылета | Причина |
|---|---|---|
WCHC (motorised wheelchair) | 48 ч | Подготовка кресла + safety check |
AVIH (animal in hold) | 48 ч | Санитарная подготовка hold + контейнер |
PETC (pet in cabin) | 24 ч | Документы животного |
UMNR (unaccompanied minor) | 24 ч | Документы сопровождения |
WCHR / WCHS (manual wheelchair) | 24 ч | Подготовка трапа / ramp |
BLND, MAAS | 24 ч | Назначение сопровождения |
| Прочие (meals, baggage, seats) | без ограничения | можно за час до вылета |
Quote with violation:
{
"detail": "SSR 'WCHC' (Инвалидная коляска (до кресла)) требует запроса
минимум за 48ч до вылета. До вылета осталось 12.5ч —
недостаточно времени для подготовки. Обратитесь в авиакомпанию
для индивидуального решения."
}GET /fares/ssr-services/
Глобальный справочник SSR (без авторизации — публичный для UI).
curl -H "X-API-Key: $PUBLISHABLE_KEY" \
"https://api.nurcore.kg/api/v1/fares/ssr-services/?category=baggage&is_active=true"Query:
| Param | Тип | Описание |
|---|---|---|
category | string | Фильтр по категории (см. таблицу выше) |
is_active | boolean | По умолчанию true |
Response 200:
[
{
"code": "BG23",
"name": "Сверхнормативный багаж 23 кг",
"category": "baggage",
"icon": "🧳",
"is_paid": true,
"default_price": 1500,
"currency": "KGS",
"requires_confirmation": false,
"is_active": true,
"notes": null
}
]default_price — это базовая цена. Фактическая цена для конкретного
рейса может быть переопределена правилами availability (см. ниже).
GET /fares/ssr-availability/by-flight
Возвращает 3 списка для конкретного рейса с учётом всех правил приоритетов.
curl -H "X-API-Key: $PUBLISHABLE_KEY" \
"https://api.nurcore.kg/api/v1/fares/ssr-availability/by-flight?\
route_id=$ROUTE_ID&\
route_type=domestic&\
aircraft_model_id=$AIRCRAFT_MODEL_ID&\
flight_duration_min=85&\
fare_family_code=CLASSIC&\
airport_code=FRU"Query (все опциональные — больше параметров = точнее матчинг):
| Param | Тип | Описание |
|---|---|---|
route_id | UUID | ID маршрута |
route_type | string | domestic / international |
aircraft_model_id | UUID | ID модели ВС |
flight_duration_min | int | Длительность рейса в минутах |
fare_family_code | string | Код fare family (LIGHT/CLASSIC/FLEX) |
airport_code | string | IATA-код аэропорта |
Response 200:
{
"available": [
{
"code": "BG23",
"name": "Сверхнормативный багаж 23 кг",
"category": "baggage",
"icon": "🧳",
"price": 1500,
"currency": "KGS",
"included_in_fare": false,
"max_per_flight": null,
"rule_applied": "тип: domestic, fare: CLASSIC",
"requires_confirmation": false
}
],
"included": [
{
"code": "MEAL",
"name": "Бортовое питание",
"category": "meal",
"price": 0,
"currency": "KGS",
"included_in_fare": true,
"included_reason": "fare: FLEX",
"requires_confirmation": false
}
],
"restricted": [
{
"code": "PETC",
"name": "Животное в салоне",
"category": "pet",
"price": 0,
"currency": "KGS",
"included_in_fare": false,
"rule_applied": "конкретная модель ВС",
"requires_confirmation": true
}
]
}Как читать ответ
available— SSR можно купить, цена вpriceincluded— SSR доступен бесплатно (включён в тариф) — покажите checkbox, отметьтеincluded_reasonдля tooltiprestricted— SSR недоступен для этого рейса (например, питание не подаётся на short-haul). Скройте в UI
max_per_flight
Если задан — это лимит на рейс по всем пассажирам и партнёрам. Например,
2 wheelchair (WCHR) на borrt. Перед POST /bookings/ рекомендуется
проверить остаток через тот же endpoint.
GET /bookings/services/categories
Возвращает категории с локализованным label и количеством активных SSR
в каждой — удобно для UI-фильтров.
curl -H "X-API-Key: $SECRET_KEY" \
"https://api.nurcore.kg/api/v1/bookings/services/categories"Response 200:
[
{"category": "baggage", "label": "Багаж", "count": 4},
{"category": "meal", "label": "Питание", "count": 6},
{"category": "seat", "label": "Места", "count": 2}
]
/services/categoriesтребует scopebooking:read→ используйтеsk_live_*(consumer_app или agency). Для публичного UI можно игнорировать категории и фильтровать клиентски по/ssr-services/.
Добавление SSR в бронь
SSR передаётся в массиве offers при создании брони
(POST /api/v1/bookings/):
curl -X POST \
-H "X-API-Key: $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"flight_id": "'$FLIGHT_ID'",
"fare_price_id": "'$FARE_PRICE_ID'",
"passengers": [{ ... }],
"contact_email": "user@example.com",
"contact_name": "John Doe",
"offers": [
{"offer_id": "BG23", "amount": 1500, "name": "Багаж 23 кг"},
{"offer_id": "VGML", "amount": 0, "name": "Вегетарианское питание"}
]
}' \
"https://api.nurcore.kg/api/v1/bookings/"Структура одного offer:
| Поле | Тип | Required | Описание |
|---|---|---|---|
offer_id | string | ✓ | Код SSR (из ssr-services или availability/by-flight) |
amount | number | — | Стоимость (если не передан — default_price из справочника) |
name | string | — | Название для отображения (опционально) |
offers суммируется в total_amount брони. Поддерживается до 9
пассажиров в одной брони, SSR применяется ко всей брони, не к
конкретному пассажиру.
Per-passenger SSR (planned): в текущей реализации
OfferItemне содержитpassenger_id. Если нужен индивидуальный SSR — создайте отдельную брони на каждого пассажира или укажите общие требования вspecial_requests.
Pricing pipeline (M2 quote_id flow)
При использовании Quote API ancillaries включены в фиксированную цену:
POST /api/v1/fares/quote— передаётеoffersи получаетеquote_idс финальной ценойPOST /api/v1/bookings/сquote_idвместоoffers— цена берётся из quote (через AncillaryPricer)- Quote живёт 300s в Redis — после успешного
POST /bookings/автоматически lock'ается
Преимущество: партнёр видит net-цену с учётом channel discount,
а agent_fee считается на quote level. Legacy путь (без quote_id) тоже
поддерживается для backward-compat.
Best practices
Mobile / website flow
- На странице рейса —
GET /ssr-availability/by-flightдля контекста → показать available + included в UI - Пользователь выбирает багаж/питание → кладёт в корзину
- На странице оплаты —
POST /fares/quoteсoffers→ finalize price POST /bookings/сquote_id→ бронь создана с финальной ценой
Кэширование
/ssr-services/справочник — кэш на стороне UI 10-30 минут (редко меняется)/ssr-availability/by-flight— кэш только в рамках сессии, не персистите между визитами (правила приоритетов могут поменяться)
Запреты (restricted)
Если SSR в restricted — скройте соответствующую опцию в UI. Не
давайте пользователю выбрать недоступную услугу — иначе POST /bookings/
вернёт 422 с детализацией.