Docs
Get an API key

Flight search best practices

Search for the real party, keep the offer with its supplier, respect expiry, and filter and sort what the supplier honours.

You need offers you can act on: fares that still exist, from the supplier that will book them, in a list short enough to show a traveller.

Search for the real party

The passenger mix is bound at offers. Send the true number of adults, children and infants with an age for everyone under twelve; a prebook with a different mix is refused with 422 passenger_mismatch, and a fare priced for one adult is not the price for two.

Keep the offer with the supplier that priced it

An offer_reference carries the supplier that priced it, and prebook, book and cancel always go there. Read meta.supplier to know who answered, and never mix references from two searches in one booking.

Prebook before the offer expires

Every offer carries expires_at. Read it rather than assuming a duration; flight fares live for tens of minutes. Fetch offers and prebook in one flow. When a reference lapses, request offers again rather than retrying the booking.

Narrow the fares

Every filter holds whichever supplier answers: the supplier applies what it can, and every fare is checked again before it is returned.

FilterKeeps a fare when
cabin_classEvery flight is in that cabin. Mixed-cabin fares are dropped.
journeys[].departure_time, journeys[].arrival_timeThat journey departs or arrives inside the window, in airport local HH:MM. A to earlier than from runs past midnight.
filters.airlines, filters.exclude_airlinesEvery flight is sold by a listed airline, and none by an excluded one, matched on marketing_carrier_code.
filters.pricetotal_amount is within min and max, in major units of currency.
filters.max_stopsEach journey has at most that many stops: 1 means at most one stop each way.
filters.max_duration_minutestotal_duration_minutes is within the limit.
filters.refundable_only, filters.changeable_onlyfare_conditions states the refund or change is allowed.
filters.checked_bag_includedincluded_baggage.checked is true.

A fare whose time, airline, cabin or duration the airline does not state is kept, because dropping it could hide a fare that fits. A fare must prove a refund, a change or a checked bag to pass those filters, because a promise you cannot keep costs the traveller money. When a fare is priced in a currency other than the one you asked for, price cannot be compared and is listed in meta.unsupported_filters. On a multi-city search, a supplier may group legs into fewer journeys than you asked for; max_stops and the journey time windows are then listed there instead of applied, because a grouped journey cannot be judged leg by leg. With Duffel, filters narrow the cheapest fares Duffel returns, at most 200, so a narrow filter such as a high price.min or a single airline can return fewer fares than exist; when meta.truncated is true, narrow the search by date, route or cabin rather than expecting more pages. max_stops: 0 or 1 is the single most effective way to keep a fare list readable.

Keep the list short and ordered

limit caps the fares returned (default 100, at most 199); when more matched, meta.truncated is present and there is no next page, so raise limit or narrow the search. sort orders by price, duration, departure, arrival or stops, ascending or descending. Each offer carries a reference of over a kilobyte, so ask for what you will show.

Price in the traveller's currency

currency asks the supplier to price in an ISO 4217 code and defaults to USD. Some suppliers price in a fixed currency regardless, so display total_amount.currency rather than the currency you asked for. country names the point of sale where a supplier uses one.

Pin a supplier only when you have a reason

Omit supplier to use the default Duffel route. Select LITEAPI explicitly when you want its inventory. For LiteAPI booking, use use_payment_sdk: true and follow Pay for a flight with LiteAPI.

Keep learning

On this page