Trip Planner
Overview
This skill turns a fuzzy request like "a week in Rome in May under $2000" into two live searches — one round-trip flight search and one hotel search on the same dates — and one combined number the user can act on. Use travel-data-api for auth, base URL, and endpoint details. Prefer the hosted MCP tools when a client is configured — both legs are available over MCP: flights on flights.flightpowers.com/mcp, hotels on hotels.flightpowers.com/mcp, and both on the free server.
The fields you will actually read: from flights, total_price_as_number, total_price, buy_link, price_range_in_relation_to_other_periods, price_insights_low, price_insights_high, and the departure_flight_arrival_description / return_flight_departure_description strings that tell you which calendar day each end of the trip lands on. From hotels, properties[].name, price, price_string, review_score, review_count, room_type, location, and link, plus the echoed checkin_date, checkout_date, applied_filters, and budget_per_night.
This is an independent API that returns publicly available flight and hotel pricing; it is not affiliated with, endorsed by, or sponsored by Google or Booking.com.
Endpoints
| Leg |
Endpoint / MCP tool |
| Round-trip flights |
POST /api/google_flights/roundtrip/v1 on google-flights-live-api.p.rapidapi.com |
| Round-trip flights (MCP) |
search_roundtrip_flights — takes departure_date_from/departure_date_to, a list of destinations, and nights |
| One-way legs (open-jaw) |
POST /api/google_flights/oneway/v1 on google-flights-live-api.p.rapidapi.com |
| One-way legs (MCP) |
search_oneway_flights — takes departure_date_from/departure_date_to and a list of destinations |
| Hotels for the stay |
POST /search on booking-live-api.p.rapidapi.com — REST only, no MCP tool exists |
| One named hotel |
POST /hotel_by_name on booking-live-api.p.rapidapi.com |
Workflow
- Resolve the request into dates and airports before calling anything. Convert the destination to an IATA airport code (Rome →
FCO). Turn "a week in May" into a concrete departure_date and return_date. Ask for the origin airport if the user did not give one — never guess it, a wrong origin makes every number downstream wrong.
- Derive nights from the dates, not from the word "week".
nights = checkout_date − checkin_date in days. 2027-05-08 → 2027-05-15 is 7 nights (8 days on the ground). A "week-long trip" is 7 nights only if the user means 7 sleeps; if they said "7 days", confirm whether that is 6 or 7 nights before you price anything.
- State the cost before you spend it. Every search is a billed request against the user's own key. Say "this is 2 calls — one flight search, one hotel search" up front. If you are comparing 3 date windows × 2 cities, that is 6 flight calls plus 6 hotel calls; get agreement first.
- Search flights first. The flight is the larger and least flexible number, and it sets the hotel envelope. Pass
max_price equal to the per-person flight ceiling you are willing to spend, currency, passengers[] (1 adult, 2 child, 3 infant on lap, 4 infant in seat), and sort_type: "Price".
- Align
checkin_date / checkout_date to the flight, not to the request. Read departure_flight_arrival_description (e.g. "8:50 AM on Mon, Jun 1"). On a red-eye or long-haul the outbound lands the day after departure_date — in that case checkin_date is the arrival day, not the departure day. Likewise if return_flight_departure_description is an early-morning slot, the traveller still needs the previous night, so checkout_date stays the return day. Recompute nights after this adjustment.
- Compute the hotel envelope, then search hotels. With a per-person budget
B, a flight total F = total_price_as_number, N nights and A adults sharing one room: room_budget = (B − F) × A and budget_per_night = room_budget ÷ N. Send that as budget_per_night, with filters: ["free_cancellation", "review_score_8"] so the shortlist is refundable and well-reviewed.
- Combine and present. Per-person total =
F + (hotel_stay_cost ÷ A). Show the gap to budget, the price_range_in_relation_to_other_periods verdict against price_insights_low/price_insights_high, both live links, and the timestamp of the search.
Search the Round-Trip Flight
export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"
curl -sS -X POST \
"https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1" \
-H "x-rapidapi-key: ${RAPIDAPI_KEY}" \
-H "x-rapidapi-host: google-flights-live-api.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d '{
"from_airport": "JFK",
"to_airport": "FCO",
"departure_date": "2027-05-08",
"return_date": "2027-05-15",
"passengers": [1, 1],
"seat_type": 1,
"currency": "USD",
"max_price": 900,
"sort_type": "Price",
"max_departure_stops": 1,
"max_return_stops": 1,
"limit": 10
}'
Search Hotels for Exactly Those Nights
checkin_date and checkout_date are the flight dates from the call above. The date span is the night count — 2027-05-08 to 2027-05-15 is 7 nights.
export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"
curl -sS -X POST \
"https://booking-live-api.p.rapidapi.com/search" \
-H "x-rapidapi-key: ${RAPIDAPI_KEY}" \
-H "x-rapidapi-host: booking-live-api.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d '{
"destination": "Rome",
"checkin_date": "2027-05-08",
"checkout_date": "2027-05-15",
"adults": 2,
"children": 0,
"currency": "USD",
"budget_per_night": 120,
"filters": ["free_cancellation", "review_score_8"]
}'
Check the echoed checkin_date, checkout_date and applied_filters in the response body against what you sent before you do any arithmetic on properties[].
Repeat Variant — Several Windows or Several Cities
There is no bulk trip endpoint. Comparing windows means repeating the pair of calls, and each iteration is a separate billed request — quote the total first.
export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"
for WINDOW in "2027-05-01|2027-05-08" "2027-05-08|2027-05-15" "2027-05-15|2027-05-22"; do
DEP="${WINDOW%%|*}"
RET="${WINDOW##*|}"
echo "=== depart ${DEP} / return ${RET} ==="
curl -sS -X POST \
"https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1" \
-H "x-rapidapi-key: ${RAPIDAPI_KEY}" \
-H "x-rapidapi-host: google-flights-live-api.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d "{\"from_airport\":\"JFK\",\"to_airport\":\"FCO\",\"departure_date\":\"${DEP}\",\"return_date\":\"${RET}\",\"passengers\":[1,1],\"currency\":\"USD\",\"sort_type\":\"Price\",\"limit\":5}"
curl -sS -X POST \
"https://booking-live-api.p.rapidapi.com/search" \
-H "x-rapidapi-key: ${RAPIDAPI_KEY}" \
-H "x-rapidapi-host: booking-live-api.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d "{\"destination\":\"Rome\",\"checkin_date\":\"${DEP}\",\"checkout_date\":\"${RET}\",\"adults\":2,\"currency\":\"USD\",\"filters\":[\"free_cancellation\",\"review_score_8\"]}"
done
When an MCP client is configured, do the flight half of this in one search_roundtrip_flights call: pass departure_date_from: "2027-05-01", departure_date_to: "2027-05-15" and nights: 7. The range bounds the departure date, not the return, so the last window in the loop above departs 2027-05-15 and returns 2027-05-22 — setting departure_date_to to the return date would silently price an extra window. One user intent is one tool call — never one call per date. The nights value you pass there is the same night count you feed to checkin_date/checkout_date on the hotel call.
Common Pitfalls
- An empty flight result is
[] with HTTP 200, not an error. It means "no flights on this route for these dates" only when X-Search-Status is ok or empty — then report it plainly and offer adjacent dates or a nearby airport, without retrying the identical call. On degraded the search did not complete: do not tell the user the trip is impossible, and do not price a trip around a flight leg you never actually searched.
- A sold-out hotel is
available: false, not a failure. On /hotel_by_name a sold-out property returns available: false with null price fields — that is a valid, correct answer, so say "not available for those nights" rather than reporting an error. On /search the equivalent is an empty properties array; loosen budget_per_night or drop a filter and say that you did.
sort_type is honoured on both endpoints. If you split a trip into two one-ways (open-jaw), you still combine and rank the two halves yourself.
use_fallback currently does nothing. It is accepted but selects a second data source that is not switched on for this API. On a long-haul or thin route, an empty result set that is often the search failing rather than genuine unavailability is exactly what X-Search-Status: degraded now tells you — retry on that signal, not on use_fallback.
- Every combination is a billed request. Three date windows across two cities is twelve calls, not one. Price the plan out loud before running it and let the user cut the matrix down.
- Never reuse or cache a fare. Fares and room rates go stale in minutes. Do not carry a price forward from earlier in the conversation, from an example, or from a previous window — re-search and stamp the result with the time it was fetched.
/search returns no nights field. Derive nights from the dates you sent, and read price_string before you multiply anything. Do not silently turn a per-night price into a stay total; if the basis is ambiguous, quote price_string verbatim next to your own arithmetic and label which is which.
- Keep the passenger set consistent across both legs.
passengers[] on the flight call and adults/children on the hotel call must describe the same travellers, or the per-person total is meaningless. State the split you used (e.g. "2 adults, one shared room").
Output Standards
- Lead with the verdict against the budget — "7 nights in Rome, 2027-05-08 to 2027-05-15: about $X per person, $Y under your $2000" — then the flight line, the hotel line, and the arithmetic that joins them, so the user can check it. Always show the derived night count and the exact
checkin_date/checkout_date you searched.
- Stamp every total with when it was fetched, quote the
price_range_in_relation_to_other_periods verdict alongside price_insights_low/price_insights_high so "$209 is typical for this route, don't rush" is available instead of a bare number, and hand over the live buy_link and hotel link for booking. Never present a fare or rate as booked or guaranteed — prices are live search results and can change before the user finishes clicking.
1---2name: trip-planner3description: Plan and price a whole trip for a named destination by combining a real-time round-trip Google Flights search with a Booking.com hotel search over the same dates, aligning checkin_date and checkout_date to the flight dates, deriving the night count, and totalling airfare plus lodging into one all-in per-person budget with filters like free_cancellation and review_score_8. Use when the user asks to plan a trip, vacation, holiday, honeymoon, city break, getaway or long weekend, or asks for flight and hotel together, a flight + hotel package, total trip cost, all-in cost, trip budget, or a per-person cost breakdown — "plan a trip to Rome for a week in May under $2000", "how much would 7 nights in Lisbon cost", "can I do Tokyo for under $3k", "10 days in Japan for a family of four", "JFK to FCO plus a hotel, budget €1500", "long weekend in Barcelona for two, £800 all in", or fit an itinerary inside a price cap in any currency. Returns the aligned checkin_date/checkout_date and night count, round-trip flights with4---56# Trip Planner78## Overview910This skill turns a fuzzy request like "a week in Rome in May under $2000" into two live searches — one round-trip flight search and one hotel search on the *same* dates — and one combined number the user can act on. Use `travel-data-api` for auth, base URL, and endpoint details. Prefer the hosted MCP tools when a client is configured — both legs are available over MCP: flights on `flights.flightpowers.com/mcp`, hotels on `hotels.flightpowers.com/mcp`, and both on the free server.1112The fields you will actually read: from flights, `total_price_as_number`, `total_price`, `buy_link`, `price_range_in_relation_to_other_periods`, `price_insights_low`, `price_insights_high`, and the `departure_flight_arrival_description` / `return_flight_departure_description` strings that tell you which calendar day each end of the trip lands on. From hotels, `properties[].name`, `price`, `price_string`, `review_score`, `review_count`, `room_type`, `location`, and `link`, plus the echoed `checkin_date`, `checkout_date`, `applied_filters`, and `budget_per_night`.1314This is an independent API that returns publicly available flight and hotel pricing; it is not affiliated with, endorsed by, or sponsored by Google or Booking.com.1516## Endpoints1718| Leg | Endpoint / MCP tool |19|---|---|20| Round-trip flights | `POST /api/google_flights/roundtrip/v1` on `google-flights-live-api.p.rapidapi.com` |21| Round-trip flights (MCP) | `search_roundtrip_flights` — takes `departure_date_from`/`departure_date_to`, a list of destinations, and `nights` |22| One-way legs (open-jaw) | `POST /api/google_flights/oneway/v1` on `google-flights-live-api.p.rapidapi.com` |23| One-way legs (MCP) | `search_oneway_flights` — takes `departure_date_from`/`departure_date_to` and a list of destinations |24| Hotels for the stay | `POST /search` on `booking-live-api.p.rapidapi.com` — REST only, no MCP tool exists |25| One named hotel | `POST /hotel_by_name` on `booking-live-api.p.rapidapi.com` |2627## Workflow28291. **Resolve the request into dates and airports before calling anything.** Convert the destination to an IATA airport code (Rome → `FCO`). Turn "a week in May" into a concrete `departure_date` and `return_date`. Ask for the origin airport if the user did not give one — never guess it, a wrong origin makes every number downstream wrong.302. **Derive nights from the dates, not from the word "week".** `nights = checkout_date − checkin_date` in days. `2027-05-08` → `2027-05-15` is **7 nights** (8 days on the ground). A "week-long trip" is 7 nights only if the user means 7 sleeps; if they said "7 days", confirm whether that is 6 or 7 nights before you price anything.313. **State the cost before you spend it.** Every search is a billed request against the user's own key. Say "this is 2 calls — one flight search, one hotel search" up front. If you are comparing 3 date windows × 2 cities, that is 6 flight calls plus 6 hotel calls; get agreement first.324. **Search flights first.** The flight is the larger and least flexible number, and it sets the hotel envelope. Pass `max_price` equal to the per-person flight ceiling you are willing to spend, `currency`, `passengers[]` (1 adult, 2 child, 3 infant on lap, 4 infant in seat), and `sort_type: "Price"`.335. **Align `checkin_date` / `checkout_date` to the flight, not to the request.** Read `departure_flight_arrival_description` (e.g. `"8:50 AM on Mon, Jun 1"`). On a red-eye or long-haul the outbound lands the day *after* `departure_date` — in that case `checkin_date` is the arrival day, not the departure day. Likewise if `return_flight_departure_description` is an early-morning slot, the traveller still needs the previous night, so `checkout_date` stays the return day. Recompute `nights` after this adjustment.346. **Compute the hotel envelope, then search hotels.** With a per-person budget `B`, a flight total `F` = `total_price_as_number`, `N` nights and `A` adults sharing one room: `room_budget = (B − F) × A` and `budget_per_night = room_budget ÷ N`. Send that as `budget_per_night`, with `filters: ["free_cancellation", "review_score_8"]` so the shortlist is refundable and well-reviewed.357. **Combine and present.** Per-person total = `F + (hotel_stay_cost ÷ A)`. Show the gap to budget, the `price_range_in_relation_to_other_periods` verdict against `price_insights_low`/`price_insights_high`, both live links, and the timestamp of the search.3637## Search the Round-Trip Flight3839```bash40export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"4142curl -sS -X POST \43 "https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1" \44 -H "x-rapidapi-key: ${RAPIDAPI_KEY}" \45 -H "x-rapidapi-host: google-flights-live-api.p.rapidapi.com" \46 -H "Content-Type: application/json" \47 -d '{48 "from_airport": "JFK",49 "to_airport": "FCO",50 "departure_date": "2027-05-08",51 "return_date": "2027-05-15",52 "passengers": [1, 1],53 "seat_type": 1,54 "currency": "USD",55 "max_price": 900,56 "sort_type": "Price",57 "max_departure_stops": 1,58 "max_return_stops": 1,59 "limit": 1060 }'61```6263## Search Hotels for Exactly Those Nights6465`checkin_date` and `checkout_date` are the flight dates from the call above. The date span *is* the night count — 2027-05-08 to 2027-05-15 is 7 nights.6667```bash68export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"6970curl -sS -X POST \71 "https://booking-live-api.p.rapidapi.com/search" \72 -H "x-rapidapi-key: ${RAPIDAPI_KEY}" \73 -H "x-rapidapi-host: booking-live-api.p.rapidapi.com" \74 -H "Content-Type: application/json" \75 -d '{76 "destination": "Rome",77 "checkin_date": "2027-05-08",78 "checkout_date": "2027-05-15",79 "adults": 2,80 "children": 0,81 "currency": "USD",82 "budget_per_night": 120,83 "filters": ["free_cancellation", "review_score_8"]84 }'85```8687Check the echoed `checkin_date`, `checkout_date` and `applied_filters` in the response body against what you sent before you do any arithmetic on `properties[]`.8889## Repeat Variant — Several Windows or Several Cities9091There is no bulk trip endpoint. Comparing windows means repeating the pair of calls, and **each iteration is a separate billed request** — quote the total first.9293```bash94export RAPIDAPI_KEY="YOUR_RAPIDAPI_KEY"9596for WINDOW in "2027-05-01|2027-05-08" "2027-05-08|2027-05-15" "2027-05-15|2027-05-22"; do97 DEP="${WINDOW%%|*}"98 RET="${WINDOW##*|}"99 echo "=== depart ${DEP} / return ${RET} ==="100 curl -sS -X POST \101 "https://google-flights-live-api.p.rapidapi.com/api/google_flights/roundtrip/v1" \102 -H "x-rapidapi-key: ${RAPIDAPI_KEY}" \103 -H "x-rapidapi-host: google-flights-live-api.p.rapidapi.com" \104 -H "Content-Type: application/json" \105 -d "{\"from_airport\":\"JFK\",\"to_airport\":\"FCO\",\"departure_date\":\"${DEP}\",\"return_date\":\"${RET}\",\"passengers\":[1,1],\"currency\":\"USD\",\"sort_type\":\"Price\",\"limit\":5}"106 curl -sS -X POST \107 "https://booking-live-api.p.rapidapi.com/search" \108 -H "x-rapidapi-key: ${RAPIDAPI_KEY}" \109 -H "x-rapidapi-host: booking-live-api.p.rapidapi.com" \110 -H "Content-Type: application/json" \111 -d "{\"destination\":\"Rome\",\"checkin_date\":\"${DEP}\",\"checkout_date\":\"${RET}\",\"adults\":2,\"currency\":\"USD\",\"filters\":[\"free_cancellation\",\"review_score_8\"]}"112done113```114115When an MCP client is configured, do the flight half of this in **one** `search_roundtrip_flights` call: pass `departure_date_from: "2027-05-01"`, `departure_date_to: "2027-05-15"` and `nights: 7`. The range bounds the *departure* date, not the return, so the last window in the loop above departs 2027-05-15 and returns 2027-05-22 — setting `departure_date_to` to the return date would silently price an extra window. One user intent is one tool call — never one call per date. The `nights` value you pass there is the same night count you feed to `checkin_date`/`checkout_date` on the hotel call.116117## Common Pitfalls118119- **An empty flight result is `[]` with HTTP 200, not an error.** It means "no flights on this route for these dates" only when `X-Search-Status` is `ok` or `empty` — then report it plainly and offer adjacent dates or a nearby airport, without retrying the identical call. On `degraded` the search did not complete: do not tell the user the trip is impossible, and do not price a trip around a flight leg you never actually searched.120- **A sold-out hotel is `available: false`, not a failure.** On `/hotel_by_name` a sold-out property returns `available: false` with null price fields — that is a valid, correct answer, so say "not available for those nights" rather than reporting an error. On `/search` the equivalent is an empty `properties` array; loosen `budget_per_night` or drop a filter and say that you did.121- **`sort_type` is honoured on both endpoints.** If you split a trip into two one-ways (open-jaw), you still combine and rank the two halves yourself.122- **`use_fallback` currently does nothing.** It is accepted but selects a second data source that is not switched on for this API. On a long-haul or thin route, an empty result set that is often the search failing rather than genuine unavailability is exactly what `X-Search-Status: degraded` now tells you — retry on that signal, not on `use_fallback`.123- **Every combination is a billed request.** Three date windows across two cities is twelve calls, not one. Price the plan out loud before running it and let the user cut the matrix down.124- **Never reuse or cache a fare.** Fares and room rates go stale in minutes. Do not carry a price forward from earlier in the conversation, from an example, or from a previous window — re-search and stamp the result with the time it was fetched.125- **`/search` returns no `nights` field.** Derive nights from the dates you sent, and read `price_string` before you multiply anything. Do not silently turn a per-night `price` into a stay total; if the basis is ambiguous, quote `price_string` verbatim next to your own arithmetic and label which is which.126- **Keep the passenger set consistent across both legs.** `passengers[]` on the flight call and `adults`/`children` on the hotel call must describe the same travellers, or the per-person total is meaningless. State the split you used (e.g. "2 adults, one shared room").127128## Output Standards129130- Lead with the verdict against the budget — "7 nights in Rome, 2027-05-08 to 2027-05-15: about $X per person, $Y under your $2000" — then the flight line, the hotel line, and the arithmetic that joins them, so the user can check it. Always show the derived night count and the exact `checkin_date`/`checkout_date` you searched.131- Stamp every total with when it was fetched, quote the `price_range_in_relation_to_other_periods` verdict alongside `price_insights_low`/`price_insights_high` so "$209 is typical for this route, don't rush" is available instead of a bare number, and hand over the live `buy_link` and hotel `link` for booking. Never present a fare or rate as booked or guaranteed — prices are live search results and can change before the user finishes clicking.