Round-Trip Flight API
A round trip is one search, not two
POST both dates and get paired itineraries, outbound and return already matched, with a combined price, duration, and one booking link.
total_price · total_duration_seconds · total_stopson every itinerary- Per-leg controls: stops, carriers, and time windows set separately for out and back
- "Empty" and "failed" stay distinguishable even across the return-leg fan-out, see search status
Free tier on RapidAPI. No card to try.
{
"from_airport": "BER",
"to_airport": "CDG",
"departure_date": "2026-10-06",
"return_date": "2026-10-13",
"limit": 5,
"currency": "usd"
}Short answer
What a round-trip search returns
POST /v1/flights/roundtrip on api.flightpowers.com (the same endpoint is /api/google_flights/roundtrip/v1 on google-flights-live-api.p.rapidapi.com with a RapidAPI key) takes a route plus departure_date and return_date, and returns one flat object per paired itinerary: outbound and return already matched, with a combined price, a combined duration, a combined stop count, one booking link, and Google's price band on the pair rather than on either leg.[
{
"from_airport": "Berlin (BER)",
"to_airport": "Paris (CDG)",
"departure_date": "2026-10-06",
"return_date": "2026-10-13",
"total_price": "$112",
"total_price_as_number": 112,
"total_duration_seconds": 12900,
"total_stops": 0,
"departure_flight_airline": "easy | Jet",
"departure_flight_duration": "1 hr 50 min",
"return_flight_airline": "easy | Jet",
"return_flight_duration": "1 hr 45 min",
"price_insights_low": 120,
"price_insights_high": 220,
"price_range_in_relation_to_other_periods": "low"
}
]| Field | Type | Meaning | Above |
|---|---|---|---|
total_price / total_price_as_number | string · number | The fare for the whole paired trip, as a display string and as a sortable number. Not the sum of two separately priced one-ways. | $112 · 112 |
total_duration_seconds | number | Flying time of both legs combined, in seconds. | 12900 |
total_stops | int | Stops across both legs together. 0 means nonstop in each direction. | 0 |
departure_flight_* / return_flight_* | fields | Each leg in full: _airline, _duration, _stops, plain-text departure and arrival descriptions, and departure_stops_info / return_stops_info per layover. | 1 hr 50 min out, 1 hr 45 min back |
buy_link | string | One Google Flights deep link for the whole paired itinerary, both legs, in the requested currency. | google.com/travel/flights?tfs=… |
price_range_in_relation_to_other_periods | "low" | "typical" | "high" | null | Google's verdict on the trip total against its price_insights_low / price_insights_high band for these dates. | low |
The return-leg fan-out happens inside the API, so a paired search bills as a single request however many outbound candidates it prices.
The band rides on the pair, which is what makes it useful here: one call answers whether the whole trip is cheap, instead of two one-ways you have to add up and then judge yourself. Same three fields as on price insights.
The same capture, rendered
A real week in Paris, $112, marked low
Berlin→Paris with both legs paired. The cheapest captured itinerary sits below Google's own band for the route, so it arrives wearing the verdict.
BER→CDG · 2026-10-06 → 2026-10-13
captured run · 2026-08-26Google's price band. Cheapest paired itinerary: $112
Each row is one object from the response. The low badge is price_range_in_relation_to_other_periods rendered directly, Google's own call that $112 is under the usual $120–$220 range for these dates.
Response shape
One object per itinerary
No leg-matching on your side: the pairing, the totals, and the single booking link are the endpoint's job.
total_price / total_price_as_numberstring · numberThe combined fare for the paired itinerary, $112 in the capture, as a display string and a sortable number. Not the sum of two separately-priced one-ways.
total_duration_secondsnumberBoth legs' flying time combined, in seconds.
total_stopsintStops across both legs: 0 means nonstop in each direction.
buy_linkstringOne Google Flights deep link for the whole paired itinerary, both legs, in the requested currency.
departure_flight_*fieldsThe outbound leg in full: departure_flight_airline, departure_flight_duration, departure_flight_stops, plain-text departure and arrival descriptions, and departure_stops_info per layover.
return_flight_*fieldsThe return leg, same structure, already matched to that exact outbound.
price_insights_low / high + verdictnumber · string | nullGoogle's band and low | typical | high verdict for the route and date pair, same as one-way. Null when Google doesn't publish a band.
Request
Every one-way control, twice
Four required fields; then each leg takes its own constraints, the part two stapled one-way searches cannot express.
Required
departure_date / return_datestringBoth travel dates, YYYY-MM-DD.
from_airport / to_airportstringIATA codes.
Optional · per leg
max_departure_stops / max_return_stopsintStop limits per leg: nonstop out, one stop back is one request.
departure_airline_codes / return_airline_codesstring[]Carrier restrictions per leg, with departure_exclude_airline_codes and return_exclude_airline_codes to remove carriers instead.
departure_departure_time_min / _maxint 0–23Outbound departure-hour window, with departure_arrival_time_min / _max for its arrival.
return_departure_time_min / _maxint 0–23The same pair of windows for the return leg.
There is no max_stops field here: on the RapidAPI endpoints use max_departure_stops / max_return_stops. (Calling through api.flightpowers.com instead, max_stops is accepted there as a convenience alias for both.)
Optional · shared
sort_type · currency · max_price · seat_type · passengers · limit · strict · use_ext_proxyExactly as on one-way, applied to the paired search as a whole.
returns_per_outboundint 1–5How many return flights to pair with each outbound flight, 1 to 5. Defaults to 2. The paired itineraries are ranked together and limit still caps how many come back. limit also sets how many outbound flights are searched (one return lookup each), so a higher limit is slower. With the default limit, 5 means the 10 results are the best of up to 50 pairings instead of 20. Not applied to results that come from the fallback source (X-Search-Fallback: used without X-Search-Notes: upstream_no_render). Must be a whole number from 1 to 5 (null is rejected).
The honest comparison
Paired search vs. two one-ways, stapled
Stapling two one-way calls together is the workaround most flight APIs leave you with. Here is what it actually costs.
Two one-way calls
- Two requests billed per date pair, so a flexible-date round-trip scan costs double.
- No combined total: you add two fares that may not be purchasable as one ticket at that price.
- Leg combinations are yours to cross-match, filter, and de-duplicate.
- Two separate booking links that never open a single round-trip purchase.
POST /roundtrip
- One request, one billed search, however many outbound candidates it prices.
total_priceis the itinerary priced as one purchase.- Legs arrive pre-paired, with per-leg filters applied inside the search.
- One
buy_linkthat reopens the exact paired itinerary.
The hard part, handled
Honest empty-vs-failed reporting is harder on round-trips than it sounds: a round-trip prices a return leg for every outbound candidate, and each of those fetches can fail on its own. empty is only reported when every candidate was attempted and every one read a real Google Flights page saying it had nothing. A fan-out that was blocked, or that stopped on the request's time ceiling, reports degraded or partial, never "no flights". The search-status page documents the full contract.
Pricing
Round-trip search on every plan
| Plan | Price / mo | Requests | $ / 1k req | Overage | Rate limit | |
|---|---|---|---|---|---|---|
| BASIC | Free | 10 / mo | — | hard cap | — | Get this plan → |
| PRO | $10 | 2,500 / mo | $4.00 | $0.003 / req | 150 / min | Get this plan → |
| ULTRArecommended | $25 | 10,000 / mo | $2.50 | $0.002 / req | 250 / min | Get this plan → |
| MEGA | $50 | 25,000 / mo | $2.00 | $0.0015 / req | 500 / min | Get this plan → |
Swipe the table sideways for overage and rate limits.
Every plan on this API includes all of its endpoints; flights and hotels are separate subscriptions. Read from the live listing on 2026-09-28; the listing is authoritative.
Questions, answered plainly
- Does the API return round-trip prices as one itinerary?
- Yes. POST /roundtrip returns one flat JSON object per itinerary with total_price, total_price_as_number, total_duration_seconds, total_stops, and both legs’ details already paired under departure_flight_* and return_flight_* fields.
- Can I set different filters for the outbound and return legs?
- Yes. Every one-way filter exists per leg: max_departure_stops and max_return_stops, departure_airline_codes and return_airline_codes (with exclude variants), and separate departure/arrival time windows for each leg. Nonstop out, one stop back with a morning return is a single request.
- Why not two one-way calls?
- Two one-way searches cost two requests per date pair, give you no combined total, and price legs independently. The sum of two one-way fares is not the fare of a round-trip ticket. The paired endpoint prices the itinerary as one purchase and ships one buy_link for it.
- Is buy_link for the whole round trip?
- Yes. One combined Google Flights deep link that reopens the exact paired itinerary, both legs, ready to book as one ticket.
- What does an empty round-trip response mean?
- Check X-Search-Status before deciding. A round-trip prices a return leg for every outbound candidate, and each of those fetches can fail on its own, so "empty" is only reported when every candidate read a real Google Flights page saying it had nothing. A blocked or truncated fan-out reports "degraded" or "partial", never "no flights".
- Do the price-insights fields work on round-trips?
- Yes. Each itinerary carries price_insights_low, price_insights_high, and the low | typical | high verdict for the route and date pair. The captured $112 BER→CDG itinerary on this page came back marked "low" against a $120–$220 band.
- How many requests does a round-trip search cost?
- One. The return-leg fan-out happens inside the API: a whole paired search, however many outbound candidates it prices, bills as a single request.
Stop stapling one-ways together
Paired itineraries with combined totals, per-leg filters, and one booking link, in a single request.
Free tier: 10 requests/month. No card to try.
Docs: the Flights API and the MCP servers.