Public Endpoints
Endpoints без авторизации — airline profile, CMS-контент, app links для website / mobile.
Публичные read-only endpoints для отображения базовой информации на
website и mobile. Не требуют X-API-Key или JWT. Защищены rate-limit
60 req/min/IP на API Gateway.
Base URL: https://api.nurcore.kg/api/v1/auth/public
Группы
| Категория | Endpoints |
|---|---|
| Airline profile | GET /airline/profile |
| Static pages | GET /page-contents, GET /page-contents/{slug} |
| Banners | GET /site-banners |
| Info blocks | GET /site-info-blocks |
| Destination ads | GET /destinations-ads |
| Mobile apps | GET /app-links |
GET /airline/profile
Информация об авиакомпании для header/footer и SEO.
curl "https://api.nurcore.kg/api/v1/auth/public/airline/profile"Response 200:
{
"airline_name": "Example Airlines",
"airline_name_en": "Example Airlines",
"iata_code": "ZM",
"icao_code": "ASB",
"callsign": "EXAMPLE",
"country": "Кыргызстан",
"country_code": "KG",
"base_airport": "FRU",
"timezone": "Asia/Bishkek",
"default_currency": "KGS",
"contact_email": "info@example-airline.com",
"contact_phone": "+996 312 999999",
"website": "https://example-airline.com",
"legal_name": "ОсОО \"Example Airlines\"",
"logo_url": "https://cdn.example-airline.com/logo.svg"
}Не возвращает: tax_id, registration_number, pnr_prefix, ticket_prefix (чувствительные внутренние поля).
GET /page-contents
Список всех публичных страниц (метаданные).
curl "https://api.nurcore.kg/api/v1/auth/public/page-contents?language=ru"Query:
| Param | Default | Описание |
|---|---|---|
language | ru | 2-буквенный код языка (ru / en / ky) |
Response 200:
[
{"id": "uuid", "slug": "about", "language": "ru", "title": "О компании", "sort_order": 1},
{"id": "uuid", "slug": "faq", "language": "ru", "title": "Часто задаваемые вопросы", "sort_order": 2},
{"id": "uuid", "slug": "terms", "language": "ru", "title": "Условия использования", "sort_order": 3}
]GET /page-contents/{slug}
Полное содержимое одной страницы.
curl "https://api.nurcore.kg/api/v1/auth/public/page-contents/about?language=ru"Path params:
| Param | Описание |
|---|---|
slug | Идентификатор страницы (about / faq / terms / privacy / contacts) |
Response 200:
{
"id": "uuid",
"slug": "about",
"language": "ru",
"title": "О компании Example Airlines",
"content": "<p>Example Airlines — национальный авиаперевозчик...</p>",
"meta_description": "Example Airlines — узнайте о нашей компании",
"sort_order": 1
}Errors: 404 если страница на указанном языке не настроена. Fallback
на UI стороне: попробовать language=ru или language=en.
GET /site-banners
Активные баннеры главной с учётом active_from / active_to.
curl "https://api.nurcore.kg/api/v1/auth/public/site-banners?language=ru"Response 200:
[
{
"id": "uuid",
"title": "Лето в Стамбуле — от 18 000 KGS",
"subtitle": "Бронируйте до 30 мая",
"image_url": "https://cdn.example-airline.com/banners/istanbul-summer.jpg",
"image_url_mobile": "https://cdn.example-airline.com/banners/istanbul-summer-mobile.jpg",
"link_url": "/search?to=IST",
"cta_text": "Купить билет",
"language": "ru",
"sort_order": 1
}
]image_url_mobile — опциональный mobile-optimized крой (например 16:9
для desktop, 4:5 для mobile). Если NULL — используйте image_url.
GET /site-info-blocks
Блоки преимуществ для главной страницы.
curl "https://api.nurcore.kg/api/v1/auth/public/site-info-blocks?language=ru&category=advantages"Query:
| Param | Описание |
|---|---|
language | ru / en / ky |
category | Опциональный фильтр (advantages / services / contacts) |
Response 200:
[
{
"id": "uuid",
"icon": "luggage",
"title": "Багаж 23 кг бесплатно",
"description": "Во всех тарифах кроме LIGHT",
"link_url": "/baggage",
"language": "ru",
"category": "advantages",
"sort_order": 1
}
]icon — короткое ключевое слово (luggage / meal / wifi / star). UI
маппит на свой icon set (Lucide / Material Icons / custom SVG).
GET /destinations-ads
Промо-направления с фото и минимальной ценой.
curl "https://api.nurcore.kg/api/v1/auth/public/destinations-ads?language=ru&origin_iata=FRU"Query:
| Param | Описание |
|---|---|
language | ru / en / ky |
origin_iata | Опционально — фильтр по аэропорту вылета (FRU / OSS) |
Response 200:
[
{
"id": "uuid",
"title": "Стамбул",
"subtitle": "Душа Турции",
"image_url": "https://cdn.example-airline.com/destinations/istanbul.jpg",
"origin_iata": "FRU",
"destination_iata": "IST",
"price_from": 18000,
"currency": "KGS",
"language": "ru",
"sort_order": 1
}
]price_from — кэшированная минимальная цена. Для актуальной цены —
звоните Schedules API.
GET /app-links
Ссылки на mobile-приложения по платформе.
curl "https://api.nurcore.kg/api/v1/auth/public/app-links"Response 200:
[
{
"id": "uuid",
"platform": "ios",
"store_url": "https://apps.apple.com/app/example-airline/id123456789",
"app_id": "com.example.airline.app",
"current_version": "1.2.0",
"min_version": "1.0.0",
"badge_url": "https://cdn.example-airline.com/badges/app-store.svg",
"sort_order": 1
},
{
"id": "uuid",
"platform": "android",
"store_url": "https://play.google.com/store/apps/details?id=com.example.airline.app",
"app_id": "com.example.airline.app",
"current_version": "1.2.0",
"min_version": "1.0.0",
"badge_url": "https://cdn.example-airline.com/badges/google-play.svg",
"sort_order": 2
},
{
"id": "uuid",
"platform": "huawei",
"store_url": "https://appgallery.huawei.com/app/C123456789",
"app_id": "com.example.airline.app",
"current_version": "1.2.0",
"badge_url": "https://cdn.example-airline.com/badges/app-gallery.svg",
"sort_order": 3
}
]Используйте min_version для force-upgrade в mobile-app при запуске.
Phone-OTP authentication
Дополнительно для passenger-flow доступна phone-based аутентификация:
| Endpoint | Назначение |
|---|---|
POST /api/v1/auth/passenger/phone/check | Проверить наличие аккаунта по номеру |
POST /api/v1/auth/passenger/phone/request-code | Запросить SMS-код |
POST /api/v1/auth/passenger/phone/verify | Подтвердить код → токены |
Flow
1. UI: POST /phone/check { phone: "+996555000000" }
→ { exists: true } или { exists: false }
2. UI: POST /phone/request-code { phone: "+996555000000" }
→ { sent: true, expires_in: 300, phone_masked: "+9965***00" }
SMS уходит на номер
3. UI: POST /phone/verify { phone: "+996555000000", code: "123456" }
→ { access_token, refresh_token, passenger }
Если аккаунта не было — создан автоматически (phone-only)Rate limits
- 1 SMS / 60 секунд / номер
- 5 SMS / час / IP
- 3 попытки ввода OTP
Errors
| Code | Сценарий |
|---|---|
| 400 | Неверный код / OTP истёк |
| 429 | Превышен rate-limit (Retry-After в заголовке) |
| 503 | SMS-провайдер недоступен |
Exchange Rates (Sprint 3.1)
Курсы валют для display в UI. Реальная оплата всегда происходит в валюте тарифа — эти курсы только для конвертации цен на отображение.
GET /fares/public/exchange-rates
curl "https://api.nurcore.kg/api/v1/fares/public/exchange-rates?\
base=KGS&source=both"Query:
| Param | Default | Описание |
|---|---|---|
base | KGS | Базовая валюта (3-letter ISO) |
source | internal | internal / nbkr / both |
Source options:
internal— внутренние курсы авиакомпанииnbkr— только из НБ КР (api.nbkr.kg, daily XML, free)both— merge с приоритетом internal
Response 200:
{
"base": "KGS",
"fetched_at": "2026-05-12T10:00:00Z",
"source": "both",
"rates": {
"USD": {"rate": 0.0117, "effective_date": "2026-05-12", "source": "internal"},
"EUR": {"rate": 0.0108, "effective_date": "2026-05-12", "source": "nbkr"},
"RUB": {"rate": 1.05, "effective_date": "2026-05-12", "source": "nbkr"},
"KZT": {"rate": 5.20, "effective_date": "2026-05-12", "source": "internal"}
}
}Семантика: rate означает "1 base = N target". То есть 1 KGS = 0.0117 USD.
GET /fares/public/exchange-rates/convert
curl "https://api.nurcore.kg/api/v1/fares/public/exchange-rates/convert?\
amount=5000&from_currency=KGS&to_currency=USD"Response 200:
{
"amount": 5000,
"converted": 58.50,
"rate": 0.0117,
"from_currency": "KGS",
"to_currency": "USD",
"source": "internal",
"effective_date": "2026-05-12"
}Не для финансовых операций. Эта конвертация только для UI display. Реальная мульти-валютная оплата требует использования Quote API с явным
target_currency.
Fallback на НБ КР
Когда source=both или nbkr и internal rate отсутствует, NurCore
вызывает api.nbkr.kg (XML feed, обновляется ежедневно). НБ КР возвращает
только курсы относительно KGS — для других base применяется
cross-rate через KGS:
USD → EUR = (KGS per USD) / (KGS per EUR)Поле source в каждой записи показывает источник: internal / nbkr /
nbkr_cross (cross-rate через KGS).
Grouped fare prices
Для страницы поиска — вся сетка fare-families одним запросом:
curl -H "X-API-Key: $PUBLISHABLE_KEY" \
"https://api.nurcore.kg/api/v1/fares/grouped-prices/?\
flight_id=$FLIGHT_ID&pax_types=ADT,CHD¤cy=KGS"Response 200:
{
"flight_id": "uuid",
"flight_date": "2026-05-15",
"route_id": "uuid",
"origin_iata": "FRU",
"destination_iata": "IST",
"currency": "KGS",
"best_family_id": "uuid-light",
"families": [
{
"fare_plan_id": "uuid-light",
"fare_plan_name": "LIGHT",
"class_of_service": "economy",
"min_total_price": 12500,
"currency": "KGS",
"refundable": false,
"changeable": false,
"baggage_allowance": "0 kg",
"cabin_baggage": "5 kg",
"prices": [
{"fare_price_id": "uuid", "passenger_type": "adult", "total_price": 12500, "...": "..."},
{"fare_price_id": "uuid", "passenger_type": "child", "total_price": 9375, "...": "..."}
]
},
{
"fare_plan_id": "uuid-classic",
"fare_plan_name": "CLASSIC",
"min_total_price": 18000,
"...": "..."
}
]
}Раньше для отображения 3 fare-families на странице рейса требовалось
3 отдельных запроса. Этот endpoint решает N+1 проблему — все families в
одном response, отсортированы по min_total_price, с готовым
best_family_id для default-выбора в UI.