const BASE_URL = 'https://www.flightics.com/api/v1' const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36' const HEADERS = { 'Content-Type': 'application/json; charset=utf-8', 'User-Agent': USER_AGENT, 'sec-ch-ua': '"Chromium";v="147", "Not.A/Brand";v="8"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"macOS"', 'Referer': 'https://www.flightics.com/' } // --- Types --- export interface PassengersCount { adult: number child: number infant: number } export interface StopConfig { locations: string[] stayRange: { min: number, max: number } stayDateRange: { begin: string, end: string } continueFromAny: boolean } export interface SearchParams { departures: string[] local: string departureDateInterval: { begin: string, end: string } stops: StopConfig[] endInSameLocation: boolean maxStops: number | null fixStopsOrder: boolean stopLength: { min: number, max: number, isSet: boolean } maxResults: number passengersCount: PassengersCount } export interface Company { name: string | null code: string icao: string } export interface Segment { id: string departureCode: string departureCity: string departureDate: string departureTimestamp: number departureDateUtc: string departureUtcTimestamp: number arrivalCode: string arrivalCity: string arrivalDate: string arrivalTimestamp: number arrivalDateUtc: string arrivalUtcTimestamp: number number: number company: Company isHidden: boolean } export interface Leg { segments: Segment[] } export interface Trip { legs: Leg[] totalCost: number bookingToken: string currency: string deepLink: string | null } export interface SearchResponse { trips: Trip[] notComplete: boolean contractVersion: number responseId: string } export interface DetailResponse { trip: Trip } export interface Country { isoCode2: string isoCode3: string nameEng: string nameNative: string phonePreselection: string } export interface InspirationItem { from: string to: string[] minPrice: number minStops: number } export interface InspirationsResponse { items: InspirationItem[] } // --- API: Search --- export async function searchTrips(params: SearchParams): Promise { return $fetch(`${BASE_URL}/trips/search`, { method: 'POST', headers: HEADERS, body: params }) } /** * Poll search until notComplete is false or maxPolls reached. * The API returns partial results with notComplete: true. * Re-calling with the same params fetches more results. */ export async function searchTripsComplete(params: SearchParams, maxPolls: number = 3): Promise { let allTrips: Trip[] = [] let lastResponse: SearchResponse | null = null for (let i = 0; i < maxPolls; i++) { const res = await searchTrips(params) allTrips = [...allTrips, ...res.trips] lastResponse = res if (!res.notComplete) break // Small delay between polls await new Promise(r => setTimeout(r, 500)) } return { trips: allTrips, notComplete: lastResponse?.notComplete ?? false, contractVersion: lastResponse?.contractVersion ?? 0, responseId: lastResponse?.responseId ?? '' } } // --- API: Trip Detail & Check --- export async function getTripDetail(bookingToken: string, local: string, passengersCount: PassengersCount): Promise { return $fetch(`${BASE_URL}/trip/detail`, { method: 'POST', headers: HEADERS, body: { bookingToken, local, passengersCount } }) } export async function checkTrip(bookingToken: string, local: string, passengersCount: PassengersCount): Promise { return $fetch(`${BASE_URL}/trip/check`, { method: 'POST', headers: HEADERS, body: { bookingToken, local, passengersCount } }) } // --- API: Inspirations --- export async function getInspirations(from: string, take: number = 100, locale: string = 'en'): Promise { return $fetch(`${BASE_URL}/inspirations/search`, { method: 'GET', headers: { 'User-Agent': USER_AGENT }, query: { from, take, locale } }) } // --- API: Weekend Search --- export async function searchWeekendTrips(params: SearchParams): Promise { return $fetch(`${BASE_URL}/trips/weekend/search`, { method: 'POST', headers: HEADERS, body: params }) } // --- API: Route Flights --- export interface RouteFlightsResponse { contractVersion: number returnResults: { trips: Trip[] }[] } export async function getRouteFlights(from: string, to: string, locale: string = 'en', passengersCount?: PassengersCount): Promise { return $fetch(`${BASE_URL}/route-flights`, { method: 'POST', headers: HEADERS, body: { from, to, locale, passengersCount } }) } // --- API: Multi-City Inspirations --- export interface MultiCityInspirationItem { from: string stops: string[] minPrice: number } export interface MultiCityInspirationsResponse { currency: { name: string, code: string, symbol: string } items: MultiCityInspirationItem[] } export async function getMultiCityInspirations(startLocationsCodes: string[], locale: string = 'en', take: number = 20): Promise { return $fetch(`${BASE_URL}/inspirations/search-multi-city`, { method: 'POST', headers: HEADERS, body: { startLocationsCodes, locale, take } }) } // --- API: Locations --- export interface Airport { id: string iata: string icao: string nameEng: string lat: number lon: number cityId: string timeZone: string timeZoneOffset: string } export interface City { id: string name: string nameEng: string countryId: string lat: number lon: number } export interface LocationCountry { id: string name: string nameEng: string isoCode2: string } export interface LocationsResponse { contractVersion: number locale: string airports: Airport[] cities: City[] countries: LocationCountry[] } export async function getLocations(): Promise { return $fetch(`${BASE_URL}/locations`, { method: 'GET', headers: { 'User-Agent': USER_AGENT } }) } // --- API: Route Data --- export async function getRouteData(departureCode: string, arrivalCode: string): Promise { return $fetch(`${BASE_URL}/route-data`, { method: 'GET', headers: { 'User-Agent': USER_AGENT }, query: { departureCode, arrivalCode } }) } // --- API: Countries --- export async function getCountries(): Promise<{ countries: Country[] }> { return $fetch(`${BASE_URL}/countries`, { method: 'GET', headers: { 'User-Agent': USER_AGENT } }) } // --- API: Booking --- export async function getBookingInfo(bookingToken: string, passengersCount: PassengersCount): Promise { return $fetch(`${BASE_URL}/booking/info`, { method: 'POST', headers: HEADERS, body: { bookingToken, passengersCount } }) } export async function initBooking(bookingToken: string, passengersCount: PassengersCount): Promise { return $fetch(`${BASE_URL}/booking/init`, { method: 'POST', headers: HEADERS, body: { bookingToken, passengersCount } }) }