Skip to main content
POST
Get live flight pricing — search by route, or re-price a known offer
Fetch live, bookable pricing for a specific route and date pair. Use it once the user has settled on exact travel dates, for example “Paris to New York departing June 1 returning June 8 in economy”. It also reprices an offer surfaced earlier by the calendar or destination tools so you can confirm availability before adding it to a trip.

Two modes, one endpoint

POST /v1/flight_search serves both modes:
  • Search mode: filter-based live search by origin, destination, departure_date, and passengers. Returns priced offers, each fare carrying a trip_item_token you can add to a trip.
  • Reprice mode: pass an offer_token from discovery (find_destination, flight_calendar) to re-price that specific offer before adding it to a trip. Route and filter fields are not allowed beside offer_token.
The CLI mirrors this: pass --offer-token for reprice mode, omit it for search mode. Omit cabin_class or send null when the user has not requested a cabin. Providers search economy by default, and the response can include other recognized cabins they return. Send economy, premium_economy, business, or first only when the user explicitly chooses that cabin. Jinko filters returned fares to match the cabin on the itinerary’s longest segment. Shorter connections may use another cabin; check segment details when presenting a mixed-cabin itinerary.

A successful search with no matches

When a live search finds no offers that match the current filters, the endpoint returns HTTP 200 with offers: [], result: "no_matches", and an instruction that asks the caller to explain that the search succeeded. When the request sent a filter that narrows the results, the instruction asks the user which filter to relax: every such filter is applied exactly as sent, so the empty result means the filter combination was too restrictive for this route and dates. Otherwise it asks whether to try other dates or airports; see Filters are always applied. The deprecated X-Jinko-Result and X-Jinko-Instruction headers carry the same outcome; read the body instead. The search answers no_matches whenever at least one airline source answered, even if another could not be searched. When some sources fail and others return offers, the response carries those offers and does not say which sources failed. A search where every source failed is an error: temporary unavailability or incomplete polling returns 503 (honor Retry-After when present and preserve the user’s filters), and a timeout returns 504. The error message is fixed per code; see Messages on supplier failures. These search rules apply to live search mode; reprice and cache-based discovery retain their existing behavior.

Offer freshness

Each fare can carry searched_at and expires_at as RFC 3339 timestamps. searched_at is when the supplier search began. expires_at is the earlier of a known supplier deadline and Jinko’s 75-minute token lifetime. When the supplier gives no deadline, it bounds token retention only. Neither field guarantees availability or price; suppliers can withdraw an offer sooner. Missing timestamps mean unknown. Repeated searches can return the same trip_item_token. Use the timestamps and latest search result to assess freshness. Complete checkout promptly; if the user pauses, search again before checkout. After expires_at, search again and replace the item. There is no universal safe maximum age, and creating a trip does not extend the offer’s lifetime.
Prices are in minor units. value is an integer — divide by 10 ** decimal_places to display it. { "value": 15977, "decimal_places": 2 } is $159.77, not $15,977. See Money & prices.

Authorizations

X-API-Key
string
header
required

Body

application/json
origin
string

3-letter IATA city or airport code. See origin_type for how an untyped code is read. origin and destination must differ. A 3-letter code the platform’s location catalog does not recognise is not refused: it is searched as an airport, and if no provider sells it the search answers result: no_matches.

Example:

"JFK"

destination
string

3-letter IATA city or airport code. See destination_type for how an untyped code is read: LAX alone is the Los Angeles CITY; send destination_type: "airport" for the airport only. origin and destination must differ. A 3-letter code the platform’s location catalog does not recognise is not refused: it is searched as an airport, and if no provider sells it the search answers result: no_matches.

Example:

"LAX"

origin_type
enum<string>

How to read the code: city searches every airport of the city, airport only that one airport. Omit it and the platform applies one rule: a code that names a multi-airport city is searched as the city; every other code is searched as the airport. Untyped NYC, LON or PAR is the city; untyped JFK, LHR or CDG is the airport; and untyped LAX, MIA or LAS — codes a city shares with its main airport — is the CITY, so results can land at any airport of that city. If the user named the airport, send airport; if they named the city, omit the field. The provider decides which airports a city holds, so a city search can return airports the catalog does not list under that code: searched as a city, LAX returns Ontario (ONT) fares, often as the cheapest offers. Each offer’s legs carry the airports flown; the offer-level origin / destination carry the city.

Available options:
city,
airport
Example:

"airport"

destination_type
enum<string>

How to read the code: city searches every airport of the city, airport only that one airport. Omit it and the platform applies one rule: a code that names a multi-airport city is searched as the city; every other code is searched as the airport. Untyped NYC, LON or PAR is the city; untyped JFK, LHR or CDG is the airport; and untyped LAX, MIA or LAS — codes a city shares with its main airport — is the CITY, so results can land at any airport of that city. If the user named the airport, send airport; if they named the city, omit the field. The provider decides which airports a city holds, so a city search can return airports the catalog does not list under that code: searched as a city, LAX returns Ontario (ONT) fares, often as the cheapest offers. Each offer’s legs carry the airports flown; the offer-level origin / destination carry the city.

Available options:
city,
airport
Example:

"airport"

departure_date
string

Departure date, YYYY-MM-DD: the local date at origin. Required in search mode, with origin and destination; not allowed beside offer_token. A date that does not exist on the calendar (2026-02-30) is refused with 422 naming the field.

Pattern: ^\d{4}-\d{2}-\d{2}$
Example:

"2026-09-01"

return_date
string

Return date, YYYY-MM-DD, on or after departure_date (a same-day return is valid). Sending it makes the search a round trip; see trip_type.

Pattern: ^\d{4}-\d{2}-\d{2}$
trip_type
enum<string>

oneway or roundtrip. Omit it and return_date decides: present is a round trip, absent a one-way trip. roundtrip requires return_date, and oneway refuses it (422 naming return_date).

Available options:
oneway,
roundtrip
cabin_class
enum<string> | null

Omit this field or send null to let the provider default the search to economy without applying a cabin filter. Send an explicit enum value to require each fare’s representative cabin to equal it. The representative cabin is the cabin on the longest flight segment; shorter connecting segments may use another cabin. An omitted or null cabin applies no cabin filter.

Available options:
economy,
premium_economy,
business,
first
Example:

"economy"

direct_only
boolean
deprecated

DEPRECATED — send max_stops: 0 instead. Still accepted: direct_only is folded into max_stops (true becomes max_stops: 0) before the search runs, so only max_stops reaches the platform. Setting it beside a non-zero max_stops is rejected.

Example:

false

max_stops
integer

Maximum stops per leg: 0 non-stop (the way to ask for direct flights), 1 one connection, 2 two. Applies to every leg of the trip.

Required range: 0 <= x <= 2
Example:

1

multi_fare
boolean

Branded fare ladder: several fares per itinerary (upsell options). Defaults to true when omitted; send false for a single fare per itinerary and a smaller response. An offer carries at most 10 fares, the cheapest fare of each cabin kept first; a provider that sells no fare ladder returns a single fare either way.

Example:

true

max_total
number

Drop fares whose total price (all passengers) exceeds this cap, in currency, major units. A fare priced in another currency is usually converted to currency with the platform’s FX rate before the comparison, but not always: a provider whose first priced offer is already in currency drops its offers in other currencies as unverifiable instead of converting them. A fare whose currency cannot be converted is not returned.

Required range: x > 0
Example:

800

include_carriers
string[]

Keep only itineraries marketed by these IATA carriers. Matching means every segment is marketed by a listed carrier (codeshares count by marketing carrier). When nothing matches, the search returns no offers with result: no_matches; the platform never widens to other carriers.

Pattern: ^[A-Za-z0-9]{2}$
Example:
exclude_carriers
string[]

Drop itineraries marketed by these IATA carriers. Must not overlap include_carriers.

Pattern: ^[A-Za-z0-9]{2}$
Example:
departure_time_range
object

Filter the OUTBOUND leg by local departure time-of-day.

arrival_time_range
object

Filter the OUTBOUND leg by local arrival time-of-day.

return_departure_time_range
object

Filter the RETURN leg by local departure time-of-day (round-trip only).

return_arrival_time_range
object

Filter the RETURN leg by local arrival time-of-day (round-trip only).

connection_time_min_minutes
integer

Shortest acceptable layover, in minutes, applied to every connection of every leg. Must not exceed connection_time_max_minutes. Conservative, like refundable_only: an itinerary with a connection whose times are unknown cannot be checked and is dropped.

Required range: x >= 0
Example:

60

connection_time_max_minutes
integer

Longest acceptable layover, in minutes, applied to every connection of every leg. Conservative in the same way as connection_time_min_minutes: a connection whose times are unknown drops the itinerary.

Required range: x >= 0
Example:

240

max_total_duration_minutes
integer

Cap each leg’s door-to-door elapsed travel time, in minutes.

Required range: x > 0
Example:

900

refundable_only
boolean

Keep only fares that can be cancelled before departure (with or without a fee). Conservative: a fare whose rules the platform cannot verify is DROPPED, so carriers that publish no rule data disappear under this filter. The filter reads the before-departure cancellation rules only; is_refundable on a returned fare is a wider reading of the same rules (it is true on a fare whose only decided rule allows cancellation after departure), so the flag is not this filter.

Example:

true

changeable_only
boolean

Keep only fares that allow a voluntary change. Conservative in the same way as refundable_only: unverifiable fares are dropped. The filter reads the before-departure change rules only; is_changeable on a returned fare is the wider reading refundable_only describes.

Example:

true

checked_bag_included
boolean

Keep only fares whose price already includes a checked bag on EVERY segment. Conservative, like refundable_only: a segment that states no allowance makes the fare unverifiable and it is dropped. The response flag of the same name is read from the first segment that states an allowance, not from every segment, so without this filter a fare flagged checked_bag_included: true can still lack a free bag on a later segment.

Example:

true

single_carrier_only
boolean

Keep only itineraries marketed end-to-end by one carrier.

Example:

true

via_airports
string[]

Restrict connections to these airports: an itinerary qualifies only when EVERY connection is one of them. Non-stop itineraries have no connection to check and are kept. Some providers are asked for at most the first 9 listed airports per leg; the whole list is still applied to what they return.

Pattern: ^[A-Za-z]{3}$
Example:
exclude_via_airports
string[]

Ban connections at these airports. Must not overlap via_airports.

Pattern: ^[A-Za-z]{3}$
Example:
aircraft_types
string[]

Keep only itineraries whose every segment flies one of these IATA equipment codes. Conservative, like refundable_only: a segment whose equipment is unknown makes the itinerary unverifiable and it is dropped, so a provider that reports no equipment (see aircraft on the segment) disappears under this filter entirely.

Pattern: ^[A-Za-z0-9]{3}$
Example:
origin_alternate_airports
string[]

ADDITIONAL departure airports searched alongside origin. Widening only — the anchor in origin is always searched, so this can add results but never remove any. THE ANCHOR DECIDES RANKING AND TRUNCATION, which makes the two airports NOT interchangeable: measured on one route, anchor JFK with alternate EWR returned 15 JFK / 35 EWR, while anchor EWR with alternate JFK returned 2 JFK / 48 EWR — 13 itineraries differed between the two. Put the airport that matters most in origin. Works with an airport or a city anchor: origin NYC with ["BOS"] searches New York's airports and Boston; an alternate inside the city is redundant and harmless. On a round trip the platform mirrors the list onto the return leg, so it also covers where the return lands. Some providers search only the anchor.

Pattern: ^[A-Za-z]{3}$
Example:
destination_alternate_airports
string[]

ADDITIONAL arrival airports searched alongside destination. Widening only — the anchor in destination is always searched, so this can add results but never remove any. THE ANCHOR DECIDES RANKING AND TRUNCATION, which makes the two airports NOT interchangeable the same way origin_alternate_airports describes: put the airport that matters most in destination. Works with an airport or a city anchor, as origin_alternate_airports describes. On a round trip the platform mirrors the list onto the return leg, so it also covers where the return departs from. Some providers search only the anchor.

Pattern: ^[A-Za-z]{3}$
Example:
nearby_airports
boolean

Also search the alternate airports around each leg’s origin and destination. Widening: more results, not fewer.

Example:

true

same_connection_airport_only
boolean

Keep only itineraries whose connections leave from the same airport they arrived at (no cross-town transfer).

Example:

true

same_origin_airport_only
boolean

Keep only round trips that return to the airport the trip departed from. Round trip only: on a one-way search it is accepted and has no effect.

Example:

true

same_turnaround_airport_only
boolean

Keep only round trips whose return departs from the airport the outbound arrived at. Round trip only: on a one-way search it is accepted and has no effect.

Example:

true

limit
integer

TOTAL number of flights to return (1–300), not a per-page size: limit: 5 returns at most five flights. Search mode only. Omit to let the platform choose: the cheapest flight plus up to 100 alternatives, so up to 101 flights. Applied after the cross-provider merge and sort, so it only trims the returned set — the providers still bound the real count.

Required range: 1 <= x <= 300
Example:

20

adults
integer
default:1

Adult travelers (12+). At most 9 travellers who need a seat: adults + children ≤ 9. Lap infants are not counted.

Required range: x >= 1
children
integer

Child travelers (2–11). At most 9 travellers who need a seat: adults + children ≤ 9. Lap infants are not counted.

Required range: x >= 0
infants
integer

Infant travelers (under 2), traveling on an adult’s lap. Seated infants (own seat) are not supported.

Required range: x >= 0
currency
string

ISO 4217 currency code, case-insensitive (eur is EUR): prices come back with the upper-case code and a display. Defaults to USD. A currency the platform cannot price in is refused with 400.

locale
string
offer_token
string

Price-check mode: re-price one known offer instead of searching a route. Route and filter fields are not allowed beside it (422); the passenger counts and currency are. Two kinds of token behave differently. A cached-itinerary offer_token from flight_calendar, find_dates, lowest_fare, find_destination or a price monitor is re-shopped LIVE on its route and dates with no cabin, stop or carrier constraint: offers[0] is the cheapest live offer with the same flights and cabin when one exists, exact_match_found says whether it did, and up to 100 alternatives follow. An offer_id from an earlier flight_search is answered from the cache of that search without re-pricing (exact_match_found: true), unless the passenger counts or currency differ, in which case it is re-shopped; once every fare of the cached offer has passed its expires_at it answers 410 OFFER_EXPIRED: search again.

Example:

"offer__3a9f1b27"

intent
object

Response

Priced offers. Every filter that narrows the results (cabin, stops, price, carriers, times, connections, fare conditions, aircraft) is applied exactly as sent: no returned offer breaks one. Options that widen a search (alternate or nearby airports) are searched where available. A search that completes and matches nothing is also a 200: offers is empty, result is no_matches and the body carries a recovery instruction. A search that could not be completed answers an error (UPSTREAM_REJECTED, UPSTREAM_ERROR, UPSTREAM_UNAVAILABLE or UPSTREAM_TIMEOUT) rather than an empty list. Offers that were found are returned even when part of the search could not be completed.

offers
object[]
required
exact_match_found
boolean

Price-check mode only (request carried offer_token): true when the live offer has the same flights as the cached one. Absent in search mode.

Example:

true

result
enum<string>

Search mode only. no_matches means the search completed and no offer matched: relay instruction, which asks which filter to relax only when the request sent a filter that narrows the results. offers is empty. Absent when offers were found. A search that could not be completed at all answers an error instead (UPSTREAM_REJECTED, UPSTREAM_ERROR, UPSTREAM_UNAVAILABLE or UPSTREAM_TIMEOUT), never an empty list.

Available options:
no_matches
instruction
string

Present with result: no_matches: what to tell the user or do next. It attributes the empty result to the filters only when the request sent a filter that narrows the results; otherwise it reads "Search completed successfully, but no flights were found for this route and dates. Ask the user whether to try other dates or airports before searching again."

Example:

"Search completed successfully, but no offers satisfied every filter sent: the filter combination is too restrictive for this route and dates. Ask the user which filter to relax before searching again."