Skip to content
This page is available in Markdown format. Markdown is recommended for AI consumption. See /api/flights/get-flight-search-results/index.md for this page, or/llms.txt for the full documentation index.

Read ranked flight results

Ranked trips as lean list cards (default 10, max 50 per page; out-of-range rejected 400), filters + sort applied.

View as MarkdownView this page as plain text
Carries onwardtripId
Settlesimmediately
Id expiresyes · 404 means search again

GET /v1/flights/searches/{searchId}/results

Ranked trips as lean list cards (default 10, max 50 per page; out-of-range rejected 400), filters + sort applied. No completion flag: re-read (300ms→3s) until snapshotFareCount holds steady across two reads AND snapshotTripCount > 0. No fares[] on a card – read the trip for fares.

Operation ID: getFlightSearchResults

Parameters

Name In Type Required Constraints Description
searchId path string yes pattern ^[A-Za-z0-9._:~=-]{1,256}$ The opaque searchId returned by createFlightSearch. Ids expire (a few minutes); a 404 means the search is gone – create a new one.
page query integer no 1..100; default 1 Page number, 1-based (max 100).
pageSize query integer no 1..50; default 10 Results per page (default 10, max 50); out-of-range values are rejected with 400, never clamped.
sort query score_desc | price_asc | duration_asc | leg1_departure_time_asc | leg1_departure_time_desc | leg2_departure_time_asc | leg2_departure_time_desc no default "score_desc" Sort mode; score_desc (default) ranks by the metasearch score, the leg1/leg2 modes sort by that leg’s local departure time.
airlines query string[] no items 1..* Airline IATA codes, repeat or comma-separate (e.g. ?airlines=SQ,TR). Values are OR’d together; by default a trip matches if ANY leg (outbound or return) carries any listed airline, not a trip-wide AND. Pass airlines-match=all for the trip-wide AND that wego.com applies.
airlines-match query any | all no - How the airlines list is matched across a trip’s legs. ‘any’ (the default) keeps a trip when ANY leg carries a listed airline. ‘all’ requires EVERY leg to, which is what wego.com does, so a Saudia-out / Emirates-back trip is dropped under ?airlines=EK. A leg marketed by two carriers still passes when one of them is listed, so add same-airline=true to require a single carrier as well. Ignored when airlines is absent.
same-airline query 0 | 1 | true | false no - Keep only trips where every leg is marketed by exactly ONE airline and it is the same airline on every leg, so an interline or self-transfer leg marketed by two carriers is dropped. Matches the MARKETING carrier only: a codeshare, where one airline sells a flight another operates, is NOT excluded, because wego.com’s ‘same airline for the complete trip’ does not exclude it either. Independent of airlines, so it works on its own; combine the two to mean ‘only SQ, on every leg’.
alliances query string[] no items 1..* Alliance codes, repeat or comma-separate. OR’d together; a trip matches if ANY leg (outbound or return) belongs to any listed alliance. Case-insensitive. NOT a fixed set – read metadata.filterOptions.alliances for this snapshot’s own values, which include upstream groupings that are not strictly alliances (lcc for low-cost carriers, value_alliance). An unknown code matches nothing rather than failing the request.
stops query integer[] no items 1..* Stop counts, repeat or comma-separate (e.g. ?stops=0,1). OR’d together; matched against the trip-level stop count (the MAX across legs, i.e. the value the response’s stops field exposes) – not a per-leg check, so a mixed-stop round trip (e.g. a direct outbound + a 1-stop return) is kept under ?stops=1.
min-price query number no 0..* Minimum cheapest-fare total price (inclusive), in the response currency.
max-price query number no 0..* Maximum cheapest-fare total price (inclusive), in the response currency.
max-duration query integer no 1..9007199254740991 Maximum total trip duration in minutes (inclusive).
min-stopover-duration query string no pattern ^\d{1,7}$ Minimum layover time in minutes (inclusive), a floor on a trip’s WORST leg. Judged per trip on the LARGEST leg total across its legs, the same fold stops applies, NOT on an individual connection: a leg with two 40-minute connections totals 80 and passes ?min-stopover-duration=60. A DIRECT trip has no layover, so it totals 0 and is DROPPED by any minimum above 0 - combine with ?stops=0 only if you want both. A trip whose layover upstream never stated is dropped by either bound rather than assumed to be 0. Read metadata.filterOptions.stopoverDurations for the span this snapshot carries, and judge the result on metadata.totalCandidates, never on the page.
max-stopover-duration query string no pattern ^\d{1,7}$ Maximum layover time in minutes (inclusive), a ceiling on a trip’s worst leg. It bounds how LONG a wait is, never when it falls: a 135-minute wait beginning 04:00 is under any sane ceiling and is still an overnight one, and a 465-minute wait beginning 11:00 is over it and never sees a night. To answer whether a wait falls overnight, read the connection’s own clock from GET /v1/flights/trips/{tripId}?view=detail, whose segments carry arrivesAt and departsAt. Judged per trip on the LARGEST leg total across its legs, NOT on an individual connection: a 2-stop leg waiting 450 then 510 totals 960 and is dropped by ?max-stopover-duration=600 even though neither connection exceeds it. Direct trips total 0, so every maximum keeps them. Each card’s legs[].layoverMinutesByStop carries the per-connection breakdown that sums to the total judged here. Read metadata.filterOptions.stopoverDurations for the span this snapshot carries, and judge the result on metadata.totalCandidates, never on the page.
outbound-departure-blocks query midnight | morning | afternoon | night[] no items 1..*; each of midnight, morning, afternoon, night Coarse local-time buckets for the OUTBOUND leg’s DEPARTURE: midnight 00:00-05:59, morning 06:00-11:59, afternoon 12:00-17:59, night 18:00-23:59, local to that airport. Repeat or comma-separate; OR’d together. The four buckets PARTITION the day, so listing all four returns every trip exactly once - wego.com’s own buckets overlap at 06:00, 12:00 and 18:00 and these do not. They are wider than they sound, so prefer the matching -range param whenever the caller gave a hard edge.
outbound-departure-range query string no pattern ^(?:\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*-\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*)?$ Minute-of-day window min-max (each 0-1439, local to that airport), both ends inclusive. When min > max the window wraps past midnight, e.g. 1320-360 means 22:00-06:00. Bounds the OUTBOUND leg’s DEPARTURE, local to the departure airport.
outbound-arrival-blocks query midnight | morning | afternoon | night[] no items 1..*; each of midnight, morning, afternoon, night Coarse local-time buckets for when the OUTBOUND leg LANDS: midnight 00:00-05:59, morning 06:00-11:59, afternoon 12:00-17:59, night 18:00-23:59, local to that airport. Repeat or comma-separate; OR’d together. The four buckets PARTITION the day, so listing all four returns every trip exactly once - wego.com’s own buckets overlap at 06:00, 12:00 and 18:00 and these do not. They are wider than they sound, so prefer the matching -range param whenever the caller gave a hard edge.
outbound-arrival-range query string no pattern ^(?:\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*-\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*)?$ Minute-of-day window min-max (each 0-1439, local to that airport), both ends inclusive. When min > max the window wraps past midnight, e.g. 1320-360 means 22:00-06:00. Bounds when the OUTBOUND leg LANDS, local to the ARRIVAL airport - this is the param for “get me in before midnight” or “nothing that lands at 4am”. Judged on the clock ALONE, not the calendar: a red-eye landing 04:00 the NEXT day reads as minute 240 and is dropped by 360-1320 exactly as a same-day 04:00 landing would be, and kept by 0-1080 exactly as a same-day one would be. Read each card’s legs[].arrivalDayOffset to tell the two apart.
return-departure-blocks query midnight | morning | afternoon | night[] no items 1..*; each of midnight, morning, afternoon, night Coarse local-time buckets for the RETURN leg’s DEPARTURE: midnight 00:00-05:59, morning 06:00-11:59, afternoon 12:00-17:59, night 18:00-23:59, local to that airport. Repeat or comma-separate; OR’d together. The four buckets PARTITION the day, so listing all four returns every trip exactly once - wego.com’s own buckets overlap at 06:00, 12:00 and 18:00 and these do not. They are wider than they sound, so prefer the matching -range param whenever the caller gave a hard edge. Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
return-departure-range query string no pattern ^(?:\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*-\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*)?$ Minute-of-day window min-max (each 0-1439, local to that airport), both ends inclusive. When min > max the window wraps past midnight, e.g. 1320-360 means 22:00-06:00. Bounds the RETURN leg’s DEPARTURE, local to that leg’s departure airport. Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
return-arrival-blocks query midnight | morning | afternoon | night[] no items 1..*; each of midnight, morning, afternoon, night Coarse local-time buckets for when the RETURN leg LANDS, i.e. when the traveller gets home: midnight 00:00-05:59, morning 06:00-11:59, afternoon 12:00-17:59, night 18:00-23:59, local to that airport. Repeat or comma-separate; OR’d together. The four buckets PARTITION the day, so listing all four returns every trip exactly once - wego.com’s own buckets overlap at 06:00, 12:00 and 18:00 and these do not. They are wider than they sound, so prefer the matching -range param whenever the caller gave a hard edge. Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
return-arrival-range query string no pattern ^(?:\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*-\s*(?:\d{1,3}|1[0-3]\d{2}|14[0-2]\d|143[0-9])\s*)?$ Minute-of-day window min-max (each 0-1439, local to that airport), both ends inclusive. When min > max the window wraps past midnight, e.g. 1320-360 means 22:00-06:00. Bounds when the RETURN leg LANDS, local to the ARRIVAL airport - the “home before 22:00” bound. Judged on the clock alone, not the calendar; read legs[].arrivalDayOffset to tell a next-day landing apart. Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
outbound-min-duration query string no pattern ^\d{1,7}$ Minimum elapsed duration of the OUTBOUND leg in minutes (inclusive). Bounds ONE leg, unlike max-duration which bounds the whole trip.
outbound-max-duration query string no pattern ^\d{1,7}$ Maximum elapsed duration of the OUTBOUND leg in minutes (inclusive). Bounds ONE leg, unlike max-duration which bounds the whole trip: a 3h outbound paired with a 14h return passes ?outbound-max-duration=300 and no trip-wide ceiling can express that.
return-min-duration query string no pattern ^\d{1,7}$ Minimum elapsed duration of the RETURN leg in minutes (inclusive). Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
return-max-duration query string no pattern ^\d{1,7}$ Maximum elapsed duration of the RETURN leg in minutes (inclusive). Bounds ONE leg, unlike max-duration which bounds the whole trip. Applies to the RETURN leg (legs[1]) ONLY. A ONE-WAY search has no return leg, so any return-* bound judges a leg that does not exist and matches NOTHING - expect metadata.totalCandidates 0, which is the honest answer rather than a silently ignored filter. Judge the result on metadata.totalCandidates, never on the page.
booking-types query wego | airline[] no items 1..*; each of wego, airline Booking types, repeat or comma-separate. OR’d together across the trip’s fares – a trip matches if ANY of its fares has a listed kind (partner fares never match either value).
booking-sites query string[] no items 1..* Provider codes, repeat or comma-separate. OR’d together across the trip’s fares – a trip matches if ANY of its fares comes from a listed provider.
stopover-airports query string[] no items 1..* Stopover airport IATA codes, repeat or comma-separate. OR’d together; a trip matches if ANY leg (outbound or return) stops over at any listed airport.
aircraft query string[] no items 1..* Aircraft type CODES, repeat or comma-separate (e.g. ?aircraft=380,789). OR’d together; a trip matches if ANY leg (outbound or return) flies any listed type. These are upstream’s short equipment codes (380, 789, 32N), NOT the display labels the results card publishes (A380, B787-9, A320 Neo) – read metadata.filterOptions.aircraft for this snapshot’s codes and the label beside each one. Several codes can share one label (321 and 32S are both A321), which is why the code is the filter key. Case-insensitive. NOT a fixed set; an unknown code matches nothing rather than failing the request.
currency query string no pattern ^[A-Z]{3}$; default "USD" Pricing currency as a 3-letter ISO 4217 code (e.g. AED). Optional; defaults to USD server-side. Not inherited from the search: a search created in one currency reads back in USD unless you pass currency on every read, so re-send the search’s currency to keep prices in it.
locale query string no length 1..35; default "en" Response language tag (e.g. en, ar). Optional; defaults to en server-side. Not inherited from the search – pass it on each read to keep results in that language.
view query card no default "card" Response projection. card is the only value: the lean results-list projection (cheapest-price summary + trip-level stops/duration + per-leg airline/aircraft/stopover, no fares[]). The former default projection was removed in issue #1308 – read GET /v1/flights/trips/{tripId} for a trip’s fares and segments.

Responses

Status Description
200 The current ranked-trip snapshot, as list cards.
400 Invalid request body/query/path parameters.
401 Missing or invalid bearer token.
404 Unknown or expired search.
429 Rate limit exceeded; retry after the Retry-After seconds.
502 The upstream flights service returned an invalid response.
503 The flights service is temporarily unavailable (upstream_unavailable) or rate-limited upstream (upstream_rate_limited); retry after the Retry-After seconds.

200 body

Field Type Always present Description
searchId string yes The id of the search this snapshot belongs to.
currencyCode string yes The currency the prices in this snapshot actually came back in, read off the fares themselves – so this, not metadata.currencyCode, is what a displayed number is denominated in. metadata.currencyCode reports what the read asked for and carries currencyCodeSource beside it; the two agree unless upstream declined to reprice into the requested currency.
metadata object yes Pagination, the snapshot’s filter vocabulary, the settle counters for this read, and what it resolved currency and locale to.
page integer yes 1-based page number of this snapshot.
pageSize integer yes Trips requested per page.
resultCount integer yes Trips on this page. The page only – judge a filter on totalCandidates, not this.
totalCandidates integer yes Trips matching this read’s filters across the whole snapshot – the count that judges a filter, never the page (results). Flights have no completion flag: settle on snapshotFareCount steady across two reads with snapshotTripCount above 0.
hasMore boolean yes Another page of trips follows.
filterOptions object yes The filter values this snapshot actually carries, ordered by count, over the same trips as snapshotTripCount. Codes are what the matching query param accepts, so pick from here rather than guessing: sending one listed code with no other filter makes metadata.totalCandidates equal that count exactly. It does NOT bound results, which stays the requested page, so compare against totalCandidates and not resultCount. Counts assume the default matching, so airlines-match=all or same-airline=true can keep fewer trips than the airlines count promises. count is trips, not legs or fares, and a trip is counted once however many of its legs or fares carry the value, including when only its return leg does. name is the display label: always present on bookingSites, where the provider code is its own fallback, present on airlines and stopoverAirports only when the snapshot dictionary resolves the code, and never present on alliances, which upstream gives no label. Still growing while the search aggregates, so judge an ABSENT code only once snapshotFareCount holds steady across two reads.
snapshotTripCount integer yes Renderable trips before filter/sort/page. 0 means upstream has produced none yet; above 0 beside an empty results means a filter or page range excluded everything. Settling needs snapshotFareCount steady across two reads AND this above 0.
snapshotFareCount integer yes Upstream progress counter, for cross-read comparison only. Runs ahead of the fares returned and stays non-zero over an empty page, so read resultCount/totalCandidates for display. Settled = equal non-zero across two reads with snapshotTripCount above 0.
createdAt string no When the upstream search was created (ISO 8601) – the freshness anchor for these prices. Absent when upstream omits it.
currencyCode string yes The currency this read ASKED upstream for, and the one every price on it is meant to be in. Read it beside currencyCodeSource before you show a number: a price computed in the wrong currency renders as a perfectly normal price, with no error and no odd shape to notice, so the response states which one rather than leaving it to be inferred. Where the operation also publishes a top-level currencyCode, that field reports the currency the prices actually came back in; the two agree unless upstream declined to reprice.
currencyCodeSource explicit | default yes How the API resolved currencyCode: explicit (the caller sent currency – including a value equal to the default) or default (USD, no currency sent). A default here is the one signal that the request never carried the currency you meant.
locale string yes The language tag this read asked upstream for – what any localized text on it was resolved in (room and board names, airline and airport names, review prose).
localeSource explicit | default yes How the API resolved locale: explicit (the caller sent locale – including a value equal to the default) or default (en, no locale sent). A default here explains text that came back in a language the caller did not ask for.
results object[] yes The requested page of ranked trips, as list cards.
tripId string yes Opaque trip id; read it back with GET /v1/flights/trips/{tripId}.
badges best_value | cheapest | cheapest_direct[] yes Every featured label that fits this trip. best_value ranks on the score of the trip’s CHEAPEST fare, the same statistic sort=score_desc orders by; cheapest and cheapest_direct break a price tie by that score, then by leg-1 departure – cheapest keeps the LATER departure, cheapest_direct the EARLIER one.
stops number yes Trip-level stop count – the MAX across legs, the same value ?stops= filters on. Do not fold legs[] yourself.
durationMinutes number yes Trip-level duration – the SUM across legs.
price object yes Card price summary – the cheapest whole-party total, fee-inclusive; scope names the (party) figure.
legs object[] yes Per-leg summary for this trip, outbound first then return.

Example

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.wego.com/v1/flights/searches/$SEARCH_ID/results"

FORM WG-REF · SEQ 004821The API and the ways in to it are early and may change.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close