Kiwi.com API: Search Fares and Cheapest Dates as JSON
Kiwi.com's own API is now for invited business partners, so most developers can't get a key for it. To read Kiwi.com fares as JSON, call GET /v1/kiwi/flights-search with origin, destination and departure_date; each successful call costs 1 credit and returns itineraries with price, carriers, stops, duration, baggage and a booking link. For a date window, GET /v1/kiwi/calendar-cheapest-dates takes a start_date and end_date in one call.
Can you still get a Kiwi.com API key?
Not unless Kiwi.com invites you. Kiwi.com used to give public access to its Tequila platform, which included the API, a white-label product and an affiliate programme. It has since narrowed that to key business partnerships, and new Tequila partnerships are by invitation only; existing partners keep their tools and documentation (Kiwi.com, 2024).
If you're a travel agency that wants to sell Kiwi.com itineraries and take bookings, the partner route is the right one: the Tequila site asks prospective affiliates to get in touch with Kiwi.com by email (2026). If you want to read fares for research, alerts or an agent, the Kiwi.com API returns what the site shows, as JSON, with the same key as every other API in the catalogue. It doesn't book anything: each itinerary carries a booking_url that opens the booking page on Kiwi.com.
What can the Kiwi.com API return?
Seven GET endpoints cover search, a single itinerary, date flexibility and destination discovery. Each costs 1 credit per successful call. The two that matter most are flights-search for one route on one date and calendar-cheapest-dates for one route across a window. locations turns a place name into the codes the other endpoints take.
| Endpoint | Use it for | Required |
|---|---|---|
/v1/kiwi/flights-search |
Itineraries for one route and date | origin, destination, departure_date |
/v1/kiwi/flights-detail |
One itinerary from a search | origin, destination, departure_date, itinerary_id |
/v1/kiwi/calendar-cheapest-dates |
Cheapest dates in a window | origin, destination, start_date, end_date |
/v1/kiwi/calendar-price-graph |
Prices across a window for a stay length | adds nights_min, nights_max |
/v1/kiwi/explore-price-map |
Destinations from one origin | origin, start_date, end_date |
/v1/kiwi/flights-one-per-city |
One flight per destination city | origin, departure_date |
/v1/kiwi/locations |
Place name to codes | query |
explore-price-map also takes a bounding box (south_west_lat, south_west_lng, north_east_lat, north_east_lng) and a limit, which is how you ask "where can I fly from London in December" for one region of the map.
How do you search Kiwi.com fares?
Send origin, destination and departure_date to GET /v1/kiwi/flights-search. Codes can be airports or cities: the recorded request below uses LON for London and BCN for Barcelona. Add return_date for a return trip. If you don't know a code, call /v1/kiwi/locations?query=London first. This is the request behind the recorded response in the next section:
curl "https://api.perceptlayer.com/v1/kiwi/flights-search?origin=LON&destination=BCN&departure_date=2026-12-04" \
-H "X-API-Key: $API_KEY"
You need a key in the X-API-Key header; get a free API key, and the authentication docs cover the rest.
Which parameters does flights-search take?
Three are required and fourteen optional. The table lists them with the types and allowed values from the endpoint definition. Nothing else is documented about defaults, although the recorded response echoes the values it used, such as cabin economy, currency EUR and sort quality.
| Parameter | Type | Notes |
|---|---|---|
origin |
string, required | Airport or city code, such as LON |
destination |
string, required | Airport or city code, such as BCN |
departure_date |
string, required | YYYY-MM-DD |
return_date |
string | For a return trip |
adults, children, infants |
integer | Passenger counts |
cabin |
string | economy, premium_economy, business or first |
max_stops |
integer | 0 for direct flights only |
min_price, max_price |
integer | Price bounds |
sort |
string | quality, price or duration |
limit |
integer | Itineraries to return |
currency, locale |
string | Display currency and language |
carriers[], exclude_carriers[] |
list of strings | Airline codes to include or exclude |
To see only direct flights on one airline, combine max_stops=0 with carriers[]=FR.
What does a flights-search response look like?
The response echoes the search, gives total_available, and lists itineraries. The recorded London to Barcelona search on 2026-12-04 found 23. Here is the first itinerary, trimmed with …:
{
"success": true,
"data": {
"trip_type": "one_way",
"origin": "LON",
"destination": "BCN",
"departure_date": "2026-12-04",
"cabin": "economy",
"currency": "EUR",
"sort": "quality",
"total_available": 23,
"itineraries": [
{
"id": "ItineraryOneWay:eyJwcm92aWRlcnMiOiJLSVdJLUJBU0lDOktJV0kiLCJyb3V0ZV9kYXRhIjoiRlI6NzgwNzpMVE46MTc5NjM5ODUwMDpCQ046MTc5NjQwNjMwMDplY29ub215OkZhbHNlOjo6IiwicHJpY2Ui…",
"price": { "amount": 29, "currency": "EUR", "formatted": "29 €" },
"duration": 7800,
"stops": 0,
"carriers": [{ "code": "FR", "name": "Ryanair", "icao": "RYR" }],
"departure": {
"airport_code": "LTN",
"city": "London",
"local_time": "2026-12-04T15:35:00"
},
"arrival": {
"airport_code": "BCN",
"city": "Barcelona",
"local_time": "2026-12-04T18:45:00"
},
"segments": [{ "flight_number": "FR7807", "cabin_class": "ECONOMY", "duration": 7800, … }],
"booking_url": "https://www.kiwi.com/en/booking/?direct=true&locale=en¤cy=eur&passengers=1-0-0&token=…",
…
},
…
]
},
…
}
The second itinerary is FR8216 from Stansted (STN) at 32 EUR, which is how you know LON searched every London airport. Times are local to each airport, so compute flight time from duration rather than from the two timestamps. Each itinerary's id is what flights-detail takes as itinerary_id, up to 2,000 characters. For what the baggage block says about the real price of a cheap fare, see what fare tracking can and cannot show.
How do you find the cheapest date to fly?
Use GET /v1/kiwi/calendar-cheapest-dates with a route and a window. It takes origin, destination, start_date and end_date, plus optional nights_min and nights_max for a return stay, and returns the cheapest dates in that window in one call. We don't have a recorded response for it, so run it in the playground on the Kiwi.com API page to see its fields and how wide a window it accepts.
curl "https://api.perceptlayer.com/v1/kiwi/calendar-cheapest-dates?origin=LON&destination=BCN&start_date=2026-12-01&end_date=2026-12-30¤cy=EUR" \
-H "X-API-Key: $API_KEY"
When you need full itineraries for every date, not only the cheapest, loop over flights-search instead. This script scans 30 departure dates and keeps the lowest price.amount for each, using only fields from the recorded response:
import datetime as dt
import os
import requests
URL = "https://api.perceptlayer.com/v1/kiwi/flights-search"
HEADERS = {"X-API-Key": os.environ["API_KEY"]}
start = dt.date(2026, 12, 1)
for i in range(30):
day = (start + dt.timedelta(days=i)).isoformat()
r = requests.get(URL, params={"origin": "LON", "destination": "BCN",
"departure_date": day, "currency": "EUR"},
headers=HEADERS, timeout=60)
if r.status_code != 200:
print(day, "error", r.json()["error"]["code"])
continue
its = r.json()["data"]["itineraries"]
if not its:
print(day, "no itineraries")
continue
best = min(its, key=lambda x: x["price"]["amount"])
print(day, best["price"]["amount"], best["carriers"][0]["code"],
best["departure"]["airport_code"], best["duration"] // 60, "min")
The script reads only fields from the recording, but we haven't run it live for this article. Each line prints the date, the lowest fare, the airline, the departure airport and the flight time in minutes. A day that fails prints its error code and costs nothing.
What does a 30-day date scan cost?
Every Kiwi.com endpoint costs 1 credit per successful call, so the cost depends on how many calls the scan takes. With flights-search, one call per departure date makes a 30-day scan 30 × 1 = 30 credits per route. With calendar-cheapest-dates, the same window is one call, 1 credit, if the endpoint accepts a 30-day range.
| Scan | Calls per route | Credits per route | Daily for 30 days |
|---|---|---|---|
flights-search, 30 dates |
30 | 30 | 30 × 30 = 900 |
calendar-cheapest-dates, one window |
1 | 1 | 1 × 30 = 30 |
Calendar, then flights-search on the 3 cheapest dates |
4 | 4 | 4 × 30 = 120 |
The last row is the usual compromise: let the calendar find the dates, then pull full itineraries only for the ones worth showing. Watching 10 routes that way daily is 120 × 10 = 1,200 credits a month, which is 1,200 − 1,000 = 200 credits a month beyond the free tier. Failed calls return X-Credits-Used: 0. See the credits docs for the balance and pricing for what packs cost.
To try it, run the London to Barcelona search above in the playground on the Kiwi.com API page, then change the date.
APIs in this post
Frequently asked questions
How much does the Kiwi.com API cost?
Each of the 7 Kiwi.com endpoints costs 1 credit per successful call, and failed calls cost nothing. A one-date fare search is 1 credit, and a 30-date scan with flights-search is 30 credits per route. Every verified account gets 1,000 free credits a month. The pricing page has what credit packs cost.
Can I book flights through this API?
No. The API reads fares and itineraries as the site shows them at the time of the call. Each itinerary includes a booking_url that opens Kiwi.com's booking page, where the traveller completes the booking. Selling and ticketing Kiwi.com itineraries yourself is what its invitation-only partner programme is for.
Are the prices final?
They're the prices the site displayed at the time of the call, and fares change often. The recorded response also shows a fare that includes a personal item but no checked bag, with checked_bag_tier_prices for adding one. Re-check a fare with flights-detail before you show it as current.
Which codes does origin accept?
Airport codes such as LTN and city codes such as LON both appear in the recorded response, which searched with LON and returned flights from Luton and Stansted. If you only have a place name, call /v1/kiwi/locations with it as query to find the code.
What happens when I hit the rate limit?
You get rate_limited (429) with a Retry-After header giving the seconds to wait, and nothing is debited. Free accounts get 1 request a second; packs include at least 5 a second. A 30-date scan at 1 request a second takes about 30 seconds. The rate limits docs explain how limits work.