Error handling

Caching and quotas: Caching & monitoring.

Platform errors (401, 403, 422, 429, 5xx, retry/backoff, rate-limit headers): Error Handling.

Endpoint error samples: Airports · Airport Search · Navaids.

Airport lookup (/airports/search)

Two distinct outcomes — same HTTP shape ({ "detail": "..." }), different meaning:

404 — ICAO not found. The code is unknown or not in the database. Common for private strips, decommissioned fields, and typos. Show Airport not found and prompt the user to verify the ICAO.

400 — neither ICAO nor IATA supplied. The endpoint requires at least one identifier. Validate before calling — an empty query string produces a 400, not a 404.

import os
import requests

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_airport(icao: str) -> dict | None:
    """Return airport data or None on 404. Raises on any other error."""
    if not icao:
        raise ValueError("ICAO code is required")
    r = requests.get(
        f"{BASE}/airports/search",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()

A 404 means the airport is not found — not a client bug. Show an empty state and let the user retry with a different code.

Text search (/airports/search/text)

ConditionBehavior
Query shorter than 2 characters422 Unprocessable Entity
Valid query, no matches200 with airports: []
Valid query, matches found200 with ranked airports array

An empty airports list is not an error — it means no airports matched the term. Render a "No results" state rather than an error banner.

def search_airports(query: str) -> list[dict]:
    """
    Returns a list of matching airports (may be empty).
    Raises ValueError for queries shorter than 2 characters.
    """
    if len(query) < 2:
        raise ValueError(f"Query must be at least 2 characters (got {len(query)!r})")
    r = requests.get(
        f"{BASE}/airports/search/text",
        headers=HEADERS,
        params={"q": query},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("airports") or []
ConditionBehavior
Airport has no published navaids200 with navaids: []
Bad bounding box400

An empty navaids array is normal — many smaller airports have no published navaids. Display a count of zero rather than an error.

def fetch_navaids(icao: str) -> list[dict]:
    """Returns navaids for an airport. Empty list is a valid result."""
    r = requests.get(
        f"{BASE}/navaids",
        headers=HEADERS,
        params={"airport": icao},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("navaids") or []

Runnable example

import os
import requests

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_airport(icao: str) -> dict | None:
    r = requests.get(
        f"{BASE}/airports/search",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def search_airports(query: str) -> list[dict]:
    if len(query) < 2:
        print(f"  [skip] query {query!r} is too short (min 2 chars)")
        return []
    r = requests.get(
        f"{BASE}/airports/search/text",
        headers=HEADERS,
        params={"q": query},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("airports") or []


def fetch_navaids(icao: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/navaids",
        headers=HEADERS,
        params={"airport": icao},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("navaids") or []


if __name__ == "__main__":
    # 1. Fetch a known airport
    airport = fetch_airport("KJFK")
    if airport:
        print(f"Airport: {airport.get('name')} ({airport.get('icao_code')})")
    else:
        print("Airport KJFK not found")

    # 2. Try a 1-char query — gracefully skipped
    results = search_airports("K")
    print(f"1-char search results: {len(results)}")

    # 3. Valid text search
    results = search_airports("Kennedy")
    print(f"Text search 'Kennedy': {len(results)} result(s)")

    # 4. Fetch navaids — empty array is valid
    navaids = fetch_navaids("KJFK")
    print(f"Navaids at KJFK: {len(navaids)}")

For transient failures (429, 5xx), use the retry helper on Error Handling.


Related: Airports · Airport Search · Navaids · Caching & monitoring