Every airport and every airline carries two different codes, and mixing them up is one of the most common bugs in flight software. JFK and KJFK point at the same airport; BA and BAW point at the same airline — but they come from two different systems, follow different rules, and are used in different places. This post explains what IATA and ICAO codes actually are, where each one is used, and how to resolve either into full airport or airline data with one API call.
The two systems, in one paragraph
IATA (International Air Transport Association) codes are the short, passenger-facing ones you see on your boarding pass and bag tag: 3 letters for airports (JFK, LHR, SYD) and 2 letters for airlines (BA, AA, SQ). ICAO (International Civil Aviation Organization) codes are the longer, operational ones used by pilots, air traffic control, and flight plans: 4 letters for airports (KJFK, EGLL, YSSY) and 3 letters for airlines (BAW, AAL, SIA). IATA is for commerce and passengers; ICAO is for operations and aviation systems.
| Airport | Airline | |
|---|---|---|
| IATA | 3 letters — JFK | 2 letters — BA |
| ICAO | 4 letters — KJFK | 3 letters — BAW |
| Used for | Tickets, bag tags, booking | Flight plans, ATC, ADS-B |

Why airport codes differ: uniqueness and structure
The key practical difference is uniqueness. ICAO airport codes are globally unique and structured: the first letter (or two) encodes a region, so every code slots into a worldwide grid.
K— contiguous United States (KJFK,KLAX,KORD)EG— United Kingdom (EGLLHeathrow,EGKKGatwick)LF— France,ED/ET— Germany,Y— Australia (YSSYSydney),RJ— Japan
IATA airport codes have no structure — they're just memorable 3-letter labels, often derived from the city name (LAX, MIA), and they are not guaranteed globally unique in the same rigorous way. That's exactly why operational systems standardized on ICAO: a flight plan or an ATC handoff can't tolerate ambiguity, but a bag tag can. When you're storing airport identifiers in a database, ICAO is the safer primary key; treat IATA as a display/booking convenience.
A subtle trap: many US airports look like their IATA code with a K bolted on (JFK → KJFK, LAX → KLAX), which tempts people to convert by string manipulation. It works often enough to be dangerous and fails everywhere else — Hawaii and Alaska use P prefixes (PHNL for HNL), and outside the US there's no relationship at all (LHR → EGLL). Never derive one code from the other; look it up.
Airline codes add a third identifier: the callsign
Airlines carry the same IATA/ICAO split, plus one more piece: the telephony callsign, the spoken name used on the radio.
- British Airways — IATA
BA, ICAOBAW, callsign "SPEEDBIRD" - American Airlines — IATA
AA, ICAOAAL, callsign "AMERICAN" - Singapore Airlines — IATA
SQ, ICAOSIA, callsign "SINGAPORE"
This matters because different data sources speak different codes. A flight number on a schedule or ticket uses the IATA airline code (BA123). A callsign on an ADS-B feed or an ATC transcript uses the ICAO code (BAW123, spoken "Speedbird 123"). If you're joining a live tracking feed to a booking system, you're joining BAW to BA — and you need a lookup that knows both.
Resolving airport codes by API
SkyLink API's airports endpoint accepts either an ICAO or an IATA code — you pass whichever one you have, and get back the full airport record with runways, frequencies, and resolved country/region:
# By ICAO
curl "https://skylink-api.p.rapidapi.com/airports/search?icao=KJFK" \
-H "X-RapidAPI-Key: $RAPIDAPI_KEY" \
-H "X-RapidAPI-Host: skylink-api.p.rapidapi.com"
# The same airport, by IATA
curl "https://skylink-api.p.rapidapi.com/airports/search?iata=JFK" \
-H "X-RapidAPI-Key: $RAPIDAPI_KEY" \
-H "X-RapidAPI-Host: skylink-api.p.rapidapi.com"Both return the same object, which conveniently echoes both codes so you can store the pair:
{
"ident": "KJFK",
"name": "John F. Kennedy International Airport",
"iso_country": "US",
"icao_code": "KJFK",
"iata_code": "JFK",
"search_code": "KJFK",
"search_type": "ICAO"
}Pass one of icao/iata, never both. This endpoint is the natural resolver when a user picks an airport from search results or when you have a code from a schedule row and need facility data.

Resolving airline codes by API
The airlines endpoint works the same way — pass an ICAO (3-letter) or IATA (2-letter) code and get back the carrier, including that all-important callsign:
curl "https://skylink-api.p.rapidapi.com/airlines/search?iata=AA" \
-H "X-RapidAPI-Key: $RAPIDAPI_KEY" \
-H "X-RapidAPI-Host: skylink-api.p.rapidapi.com"[
{
"name": "American Airlines",
"iata": "AA",
"icao": "AAL",
"callsign": "AMERICAN",
"country": "United States",
"active": "Y",
"logo": "https://media.skylinkapi.com/logos/AA.png"
}
]Two behaviors to code for. First, the airlines endpoint returns an array (usually one item), and an unknown code returns HTTP 200 with an empty array [], not a 404 — plan for a "carrier not found" placeholder, not an error state. Second, several fields (iata, icao, callsign) can be null for obscure or defunct carriers, so don't assume every airline has all three identifiers.
A practical pattern: normalize on ingest
The cleanest architecture resolves codes once, at the edge, and stores the full set. When a flight or booking enters your system with whatever code it happened to carry, look it up and persist the ICAO, IATA, and (for airlines) callsign together. From then on your internal joins are unambiguous: match ADS-B callsigns to bookings via the stored ICAO↔IATA airline pair, and key airports on ICAO while displaying IATA. Chain the airport/airline lookups with aircraft registration lookup and flight status and you can turn a single raw identifier — a tail number, a hex code, a flight number — into a fully labeled record.
SkyLink API gives you a free tier of 1,000 requests/month to test airport and airline lookups against, with paid plans starting at $18.59/mo once you're ready for production traffic. It's available through the free trial — sign up, grab a key, and resolve ICAO or IATA codes in a single call.
