SDKs & Examples
TypeScript Client
Минимальный TypeScript wrapper для NurCore API.
Готового npm-пакета пока нет. Ниже — компактный standalone wrapper, который можно скопировать в свой проект и адаптировать.
Базовый client
type ApiOptions = {
baseUrl: string;
apiKey: string; // тип клиента и client_id определяются по самому ключу на сервере
};
class NurCoreClient {
constructor(private opts: ApiOptions) {}
private async request<T>(path: string, init: RequestInit = {}): Promise<T> {
const headers: Record<string, string> = {
"Content-Type": "application/json",
"X-API-Key": this.opts.apiKey,
...((init.headers as Record<string, string>) || {}),
};
const res = await fetch(`${this.opts.baseUrl}${path}`, { ...init, headers });
if (!res.ok) {
const detail = await res.json().catch(() => ({}));
throw Object.assign(new Error(detail.detail || res.statusText), {
status: res.status,
detail: detail.detail,
headers: Object.fromEntries(res.headers.entries()),
});
}
if (res.status === 204) return undefined as T;
return res.json();
}
get<T>(path: string, qs?: Record<string, any>) {
const url = qs ? `${path}?${new URLSearchParams(qs as any)}` : path;
return this.request<T>(url);
}
post<T>(path: string, body?: any) {
return this.request<T>(path, {
method: "POST",
body: JSON.stringify(body || {}),
});
}
patch<T>(path: string, body?: any) {
return this.request<T>(path, {
method: "PATCH",
body: JSON.stringify(body || {}),
});
}
delete<T>(path: string) {
return this.request<T>(path, { method: "DELETE" });
}
}
export const api = new NurCoreClient({
baseUrl: "https://api.nurcore.kg/api/v1",
apiKey: process.env.NURCORE_API_KEY!,
});Примеры
Поиск рейсов
interface Flight {
id: string;
flight_number: string;
scheduled_departure: string;
scheduled_arrival: string;
status: string;
total_seats: number;
booked_seats: number;
}
const result = await api.get<{ data: Flight[]; total: number }>(
"/schedules/flights/",
{ route_code: "BSZ-OSS", flight_date: "2026-05-10" }
);
console.log(`Found ${result.total} flights`);Создание брони
interface Booking {
id: string;
booking_reference: string;
status: string;
total_amount: number;
currency: string;
expiry_date: string | null;
}
const booking = await api.post<Booking>("/bookings/", {
flight_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",
});
console.log(`Created PNR: ${booking.booking_reference}`);Magic-link flow (без X-API-Key)
async function loadPublicBooking(bookingId: string, accessToken: string) {
const res = await fetch(
`https://api.nurcore.kg/api/v1/bookings/${bookingId}/public?access_token=${accessToken}`
);
if (!res.ok) throw new Error("Failed");
return res.json();
}
async function consumerCheckin(
bookingId: string,
passengerId: string,
flightId: string,
seatNumber: string,
accessToken: string
) {
const res = await fetch(
`https://api.nurcore.kg/api/v1/checkin/consumer?access_token=${accessToken}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
booking_id: bookingId,
passenger_id: passengerId,
flight_id: flightId,
seat_number: seatNumber,
}),
}
);
if (!res.ok) throw new Error("Checkin failed");
return res.json();
}React + TanStack Query
import { useQuery, useMutation } from "@tanstack/react-query";
export function useBooking(id: string) {
return useQuery({
queryKey: ["booking", id],
queryFn: () => api.get(`/bookings/${id}`),
enabled: !!id,
});
}
export function useConfirmBooking() {
return useMutation({
mutationFn: (id: string) => api.post(`/bookings/${id}/confirm`, {}),
});
}Best practices
- Не размещайте API Key в frontend-bundle. Используйте серверный proxy (BFF — Backend for Frontend), который добавляет заголовки и пробрасывает запросы.
- Для magic-link flow X-API-Key не нужен — token уже встроен в URL.
- Кешируйте справочники (airports, fare-families) на стороне клиента.