How to add a flight search API to your website: a step-by-step integration guide
A practical build order for flight search on your own site: server-side architecture, validation, results, caching, price re-checks and safe booking retries.
Qasim Hussain
Founder · Published

Adding a flight search API to your website looks like one HTTP call. The work that makes it reliable sits around that call: where the key lives, how you validate input, how you display times, and what happens between the search and the booking. This guide walks through the integration in the order we recommend building it.
The examples follow the general shape of the IATA.co flights API. They are illustrative: the full reference, with every field and error code, comes with an approved key. If the concept is new to you, start with what a flight API is. If you are still choosing a supplier type, read GDS vs NDC vs flight aggregator API first.
Architecture first: the browser never calls the flight search API
Your front end talks to your server, and your server talks to the flights API. An API key shipped inside JavaScript is public the moment the page loads, and anyone who copies it can spend your search allowance. Keep the key in an environment variable or a secret manager on the server, never in the repository and never in the front-end bundle.
There is a second reason. On IATA.co, keys only work from whitelisted server IP addresses, so a call from a visitor browser would be refused anyway. The address that gets whitelisted is the outbound IP of your server. If you deploy on serverless functions or autoscaling containers with rotating addresses, route API traffic through a fixed egress address first. We cover this in detail in rate limits, caching and IP whitelisting.
- Browser: collects the search, displays results, holds no credentials.
- Your server: validates input, holds the key, calls the API, caches, logs, and owns the order state.
- Flights API: searches suppliers, returns offers, re-checks the price and creates the booking.
To get a key for our flights API, you create a free account, verify your email and request access from the dashboard. A person reviews the request. After approval you receive the key and the documentation.
Build the search form and validate it twice
An illustrative search request is POST /api/v1/flights/search with a JSON body. The fields map directly to the form your users see:
originanddestination: three-letter IATA airport codes such asLHRorDXB. Uppercase them, require exactly three letters, and reject a search where both are the same.departure_dateandreturn_date: ISO 8601 dates inYYYY-MM-DDform. The departure cannot be in the past, the return cannot be before the departure, andreturn_dateis only sent for a round trip.trip_type: one-way or round-trip. Let this field drive whether the return date is shown at all.cabin: economy, premium economy, business or first.adults,children,infants: whole numbers. Require at least one adult, and do not allow more infants than adults, because a lap infant travels with one adult.
Validate in the browser for a fast, friendly form, then validate again on the server, because the server is the only place you can trust. Every request you reject locally is a search that does not count against your monthly plan allowance.
Airport autocomplete
Travellers type city names, not codes. Autocomplete turns "London" into a choice between its airports. Serve suggestions from your own server, using a local airport dataset (code, airport name, city, country) or a lookup endpoint if your provider offers one.
Airport codes are assigned by the International Air Transport Association (IATA), which publishes an official airline and airport code search. IATA.co is an independent platform and is not affiliated with the association. We use the same public codes every booking system uses.
Debounce keystrokes, wait for at least two characters, match on code, city and airport name, and rank exact code matches first. Some cities also have a metropolitan code that covers several airports. Decide whether you support those, and check that your provider accepts them, before you show them in the list.
Send the search and handle partial results
A flight search fans out to suppliers, so it is slower than a typical API call. Providers handle this in one of two ways. A synchronous search returns the full result set in one response. An asynchronous search returns a search identifier straight away, and you poll for results as suppliers answer.
Check the reference of your provider to see which model applies. If results arrive in parts, the flow looks like this:
- Send the search from your server and store the returned search identifier.
- Render the first batch of results as soon as it arrives, with a visible loading state.
- Poll at the interval the provider recommends. Every poll is a request and counts against your requests per minute.
- Stop when the response says the search is complete, or when your own timeout is reached, and show what you have.
- Cancel polling when the user edits the search or leaves the page.
In both models, set a server-side timeout, disable the search button while a request is in flight, and show progress. A user who sees nothing will click again, and you pay for the duplicate.
Normalise and display the results
Map the API response into your own internal model before it reaches a template. If a field changes later, or you add a second supplier, the change stays in one mapping file.
- Offer: identifier, total price, currency, price per passenger type, and the expiry time if one is provided.
- Journey: outbound and return, each made of one or more segments.
- Segment: marketing and operating carrier, flight number, departure and arrival airports, local times and duration.
- Stops: the number of segments minus one, with the layover time at each connection.
- Baggage: cabin and checked allowance per passenger type. Say "not included" clearly when it is not.
- Fare rules: whether the fare can be refunded or changed, and the penalties that apply.
Time zones: always show local airport times
A departure time is local to the departure airport. An arrival time is local to the arrival airport. Never convert either to the time zone of the visitor. This is the most common display bug in flight results, and it usually comes from passing a timestamp through a JavaScript Date object, which silently applies the browser zone.
Treat the times as wall-clock strings and format them without time zone conversion. Use the duration the API returns instead of subtracting one local time from another. When the arrival falls on a later calendar day, mark it with a "+1" label next to the time.
Filter and sort on your side
Once the normalised results are in memory, filtering and sorting need no further API calls. Common filters are number of stops, airline, departure and arrival time windows, price range and included baggage. Common sorts are cheapest, fastest and a blended "best" score of price and duration.
Build the filter options from the result set itself, so you never show an airline that has no offers. If every filter click triggered a new search, you would burn through your plan and hit the per-minute limit for no benefit.
Caching strategy and cache keys
On IATA.co, identical searches within a short window are answered from cache. A cache on your side still earns its place: it serves the back button, pagination and two users who search the same route minutes apart, without a network round trip.
The cache key must contain every parameter that changes the result: origin, destination, both dates, trip type, cabin, the three passenger counts and the currency. Normalise first (uppercase codes, fixed field order), then join or hash the values. A key that forgets the infant count will sooner or later show one user the prices of another search.
Keep the lifetime short, in minutes and not hours, because fares and availability move. Do not store an error or a partial result as if it were final. A cached price is a display price only and is never the basis for a booking.
Re-check the price before booking
Between the search and the booking, a fare can sell out or change. With our API, price and availability are always re-checked with the supplier before a booking is confirmed. Your interface needs a path for each of the three outcomes:
- Unchanged: continue to passenger details and confirmation.
- Changed: show the old and the new total side by side and ask for explicit confirmation. Never accept a higher price silently.
- No longer available: return the user to the results with a fresh search.
IATA.co bookings are deducted from a prepaid balance, and every movement appears in the ledger. Make sure your flow also handles the case where the balance does not cover the confirmed total, and alert your team before the balance runs low.
Collect clean passenger data
Most problems after booking start with passenger data. Correcting a name after ticketing can be costly, and with some fares it is not possible at all, so validate before you send.
- Names: given names and surname exactly as printed in the passport, in Latin letters, with no nicknames.
- Date of birth: check it against the passenger type on the travel dates. An infant must still be an infant on the return flight.
- Document data: number, nationality, issuing country and expiry date for international trips. Warn when the passport expires close to the travel date, since entry rules differ by destination.
- Contact: an email address and a phone number in international format, so schedule changes reach the traveller.
You do not need your own accreditation to book through us (here is how that works), but you stay responsible for your customers and for the fare rules. Show those rules and the baggage allowance before payment.
Make bookings safe to retry
Idempotency keys on booking requests
A search can be repeated without harm. A booking cannot: send it twice and you may create two bookings and two balance deductions. The hard case is a timeout, where you do not know whether the first request arrived.
An idempotency key solves this. It is a unique value you generate once per booking attempt and send with the request, so the server can recognise a retry. The IETF HTTP API working group describes the pattern in its Idempotency-Key header draft. It is an Internet-Draft and not a finished standard. It recommends a UUID or a similar random identifier, and states that a key must not be reused with a different payload.
Generate the key when the user reaches the confirm step, store it with your order record, and reuse it for every retry of that order. Check the reference of your provider for the exact mechanism it supports. Where none exists, look up the booking status before any retry and guard the step with your own order state.
Errors, 429 and backoff
Sort errors into classes. A validation error means your request is wrong, so fix it and do not retry. An authentication or permission error usually means a bad key or an IP address that is not whitelisted, so alert your team. Server errors and timeouts on a search can be retried. On a booking, retry only under the protection described above.
MDN describes 429 Too Many Requests as the response a server sends when a client has made too many requests in a given time. The server may add a Retry-After header, either as a number of seconds or as an HTTP date. Honour it. When it is absent, use exponential backoff with random jitter and a cap on attempts.
Our responses carry rate-limit headers. Read them on every response and slow down before you reach the limit, which is cheaper than recovering after it.
Log request IDs
Log each API call with a timestamp, endpoint, status code, latency, your own correlation ID and any request ID the API returns. Never log the API key or full document numbers. When you need help with a failed booking, a request ID is the fastest route to an answer.
Test in a sandbox, then go live
Ask your provider what test environment or test mode it offers, and how test bookings are kept apart from real ones. Then run the unpleasant scenarios on purpose: no results, a price change, a sold-out fare, a timeout during booking, a 429 response and a call from an IP address that is not whitelisted. Include a party with an infant and a round trip in every cabin.
Before you switch to production, work through this checklist:
- The API key lives in a server-side secret store, not in the repository or the front-end bundle.
- The production server has a static outbound IP address, and that address is whitelisted.
- Server-side validation covers every field, including the rule that infants cannot outnumber adults.
- Times are shown as local airport times, and next-day arrivals are flagged.
- Cache keys include every search parameter, and lifetimes are short.
- A price change stops the flow and asks the user for explicit confirmation.
- Booking requests are protected against duplicates, and the confirm button is disabled after the first click.
- The client honours 429 and Retry-After, with backoff, jitter and a cap on retries.
- Logs capture request IDs and exclude secrets and document numbers.
- Someone is alerted when the prepaid balance runs low.
- Fare rules and baggage are visible before payment.
Build your flight search API integration with IATA.co Create a free account, verify your email and request API access from the dashboard. A person reviews every request, and once yours is approved you receive your key and the full documentation. You can use the browser booking portal from the same account while you build.
Questions people ask
Put the API behind your own server: the browser sends the search to your back end, and your back end calls the API with the key. Then build the form and validation, normalise the results, add caching, and handle the price re-check and the booking step. Test the failure cases before going live.
You should not. Any key shipped to the browser is public and can be copied. On IATA.co it would not work in any case, because keys are only accepted from whitelisted server IP addresses.
Search results reflect availability at the moment of the search, and they may come from a cache. Seats in a fare class can sell out minutes later. That is why price and availability are re-checked with the supplier before a booking is confirmed, and why your site should ask the user to accept any new total.
Keep it short, in the range of minutes, and treat cached prices as display prices only. Build the cache key from every search parameter, including dates, cabin, passenger counts and currency. Always rely on the live re-check before booking and never on the cached value.
Not on IATA.co. You book through us, so you do not need your own accreditation, although you remain responsible for your customers and for the fare rules. IATA.co is an independent platform and is not affiliated with the International Air Transport Association (IATA).
- #flight api
- #api integration
- #developers
- #caching
- #idempotency
- #error handling
Found this useful? Share it.






