# Ignav > Self-serve API for live flight prices and booking links. Search one-way, round-trip, multi-city, and open-jaw fares across thousands of routes, then get direct booking URLs for the itineraries your users choose. Data comes from multiple proprietary sources, merged and normalized. Base URL: https://ignav.com/api. Fare and booking endpoints use POST with a JSON body; airport search and health checks use GET. A machine-readable OpenAPI spec is at https://ignav.com/openapi.json. ## Authentication Fare search, booking link, and airport search requests require an API key in the `X-Api-Key` header. The health check does not. Sign up for a free account at https://ignav.com/signup to get a key; view and rotate it at https://ignav.com/dashboard. Your first 1,000 requests are a one-time free allowance that does not reset monthly; no credit card is required. There is no provider-imposed per-account request throttle. Accounts can optionally set a monthly spending limit; requests stop at that cap until the limit changes or a new billing cycle begins. ``` X-Api-Key: YOUR_API_KEY ``` ## MCP Server Ignav also runs a hosted MCP server at https://ignav.com/mcp using Streamable HTTP. Point any MCP client at that URL to give an agent live flight search with booking links. Tools: - `search_airports`: resolve cities, airport names, metro areas, or codes into IATA airport codes. - `search_flights`: search one-way or round-trip fares. Returned itineraries include `booking_url`; preserve the full URL when showing results to users. MCP tool calls require an Ignav account so usage belongs to one account instead of a shared cloud connector IP. Cloud ChatGPT and Claude custom connectors use OAuth with the MCP server URL `https://ignav.com/mcp`. Local/header-capable MCP clients can send an API key as `Authorization: Bearer YOUR_API_KEY` or `X-Api-Key: YOUR_API_KEY`. MCP calls bill like API requests: 1,000 free successful requests, then $2.00 per 1,000 successful requests. ## For AI agents Agent-facing setup guide: https://ignav.com/docs/agents. Test without signup at https://ignav.com/playground. Use https://ignav.com/mcp with OAuth or an API key. To get your own key, use https://ignav.com/signup with a mailbox you can read. Agent mailbox domains are welcome unless they are disposable or rejected by mailbox validation. Signup requires a solved proof-of-work challenge: the signup page handles it automatically, so a browser is the easiest path. For raw HTTP, request a challenge with POST https://ignav.com/api/auth/altcha-challenge (JSON body {"email": "..."}), solve it (ALTCHA format), and send the solution as the `altcha` field in the signup payload. Signup creates a session cookie immediately and redirects to https://ignav.com/dashboard?welcome=1. Verify through https://ignav.com/verify-email?token=... or GET https://ignav.com/api/auth/verify?token=... Read your key at https://ignav.com/dashboard. If already session-authenticated, GET https://ignav.com/api/account/me and read `api_key`. There is no unauthenticated key-by-email endpoint. Use `X-Api-Key` for REST API calls. For MCP, cloud clients can use OAuth and local clients can use `Authorization: Bearer YOUR_API_KEY` or `X-Api-Key`. If you hit HTTP 402 `billing_required`, give https://ignav.com/dashboard to your human so they can add billing. The error body includes pricing. Preserve `booking_url` and returned booking link URLs verbatim. Only successful requests are billed. ## GET /api/health Public, unauthenticated, and unmetered liveness check. A successful response is `{"ok": true, "release": "DEPLOYED_RELEASE"}` with `Cache-Control: no-store`. It confirms that the API process is serving requests; it does not run a fare search or verify every external dependency. ## POST /api/fares/one-way Search one-way flights between two airports or metro areas on a date. For multi-city, open-jaw, or other trips with multiple ordered legs, use `POST /api/fares/search` instead. Key request params: - `origin` (string, required): 3-letter IATA airport or metro code, e.g. SFO or LON. - `destination` (string, required): 3-letter IATA airport or metro code, e.g. JFK or PAR. - `departure_date` (string, required): YYYY-MM-DD. - `adults`, `children`, `infants_in_seat`, `infants_on_lap` (integers, optional): passenger mix. Default 1 adult; max 9 total passengers. - `cabin_class` (string, optional): "economy" (default), "premium_economy", "business", or "first". - `max_stops` (integer, optional): 0, 1, or 2. Omit to allow any. - `min_carry_on_bags`, `min_checked_bags` (integers, optional): minimum included bags. - `max_price` (integer, optional): strict maximum price in the market's currency. - `departure_time_range` (object, optional): earliest_hour, latest_hour, arrival_earliest_hour, arrival_latest_hour (0-23, airport-local time). - `airlines_include` / `airlines_exclude` (string[], optional): 2-character airline codes; a code cannot appear in both arrays. - `allow_self_transfer` (boolean, optional): allow itineraries identified as requiring separate tickets. Setting false is a best-effort filter; same-carrier separate tickets may not be identifiable. Default true. - `market` (string, optional): 2-letter country code for pricing locale, e.g. "US" (default), "GB". ``` curl -X POST "https://ignav.com/api/fares/one-way" \ -H "X-Api-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"origin":"SFO","destination":"JFK","departure_date":"FUTURE_DEPARTURE_DATE"}' ``` Replace `FUTURE_DEPARTURE_DATE` with a future date in `YYYY-MM-DD` format. Response: `{origin, destination, departure_date, itineraries}`. Each itinerary has `price` ({amount, currency, status}, where status is "verified" or "unverified"), an `outbound` leg ({carrier, duration_minutes, segments}), `cabin_class`, `requires_self_transfer`, optional `bags` ({carry_on, checked}), and an `ignav_id` (unique ID used to fetch booking links). `requires_self_transfer` is a best-effort indication; false does not guarantee a protected through-ticket, especially for same-carrier connections. Each segment has marketing_carrier_code, flight_number, operating_carrier_name, departure/arrival airport, local times, IANA timezones, UTC timestamps, duration_minutes, and aircraft. An empty `itineraries` array is a valid successful response. ## POST /api/fares/round-trip Search round-trip flights. Accepts all one-way parameters, plus: - `return_date` (string, required): YYYY-MM-DD, on or after departure_date. - `return_time_range` (object, optional): same format as departure_time_range, local time for the return leg's airports. ``` curl -X POST "https://ignav.com/api/fares/round-trip" \ -H "X-Api-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"origin":"SFO","destination":"LHR","departure_date":"FUTURE_DEPARTURE_DATE","return_date":"FUTURE_RETURN_DATE"}' ``` Replace both date placeholders with future dates in `YYYY-MM-DD` format, with the return date on or after departure. Response: same shape as one-way; round-trip itineraries add an `inbound` leg object with the same structure as `outbound`. ## POST /api/fares/search Search one or two ordered flight legs in one request, including multi-city and open-jaw trips. Dates must be chronological. Request body: - `legs` (array, required): one or two ordered leg objects. Each leg requires `origin`, `destination`, and `departure_date`; origins and destinations accept airport or metro IATA codes. Each leg may also set `max_stops` and `departure_time_range`. - Passenger mix, `cabin_class`, baggage, price, airline, self-transfer, and `market` fields use the same formats as one-way search. ``` curl -X POST "https://ignav.com/api/fares/search" \ -H "X-Api-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legs":[{"origin":"SFO","destination":"DEN","departure_date":"FUTURE_DATE_1"},{"origin":"COS","destination":"ORD","departure_date":"FUTURE_DATE_2","max_stops":0}]}' ``` Response: `{legs, itineraries}`. Each itinerary is a ranked complete journey with a trip-level `price` ({amount, currency, status}), an ordered `legs` array matching the request, `requires_self_transfer`, and an `ignav_id`. `requires_self_transfer` is a best-effort indication; false does not guarantee a protected through-ticket, especially for same-carrier connections. Pass that ID to the booking-links endpoint using the same account. The ID is an opaque handoff token, not a stable identifier across separate searches. Flexible-search booking options use zero-based `leg_indexes` to identify the legs covered by each option. ## POST /api/fares/booking-links Get direct booking URLs for a specific flight, two ways: 1. By ID (preferred): pass the `ignav_id` from a fare search itinerary. 2. Manually: pass `origin`, `destination`, `departure_date`, `outbound_carrier_code` (2-character airline code), `outbound_flight_number`, optionally `return_date` + `inbound_carrier_code` + `inbound_flight_number` for round trips, passenger fields, and `market`. ``` curl -X POST "https://ignav.com/api/fares/booking-links" \ -H "X-Api-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"ignav_id":"5e4fcd2f1dc340649eb19f6ee2afb57a"}' ``` Response: `{itinerary, booking_options}`. Treat the returned `itinerary` as current; a stale flexible-search handoff may be refreshed before links are resolved. Fare-search responses describe flights and airlines; sellers and OTAs appear in `booking_options` only when a usable link is available for the selected itinerary and market. `booking_options` contains zero or more purchase options (empty when no usable links are available). One-way and round-trip options have a `legs` array (e.g. ["outbound"]); flexible-search options instead have zero-based `leg_indexes`. An open-jaw or multi-city itinerary may return one separately purchased airline-direct one-way option per leg, but only when every leg is covered. Every option has a `links` array; each link has `provider_name`, `provider_type` ("airline" or "third_party"), optional `fare_name` and per-offer `price`, and a `url`. ## GET /api/airports Search airport-level IATA codes by code, airport name, city, or country. Query params: - `q` (string, required): search query, at least 2 characters. - `limit` (integer, optional): max matches. Default 10, max 20. ``` curl "https://ignav.com/api/airports?q=san+fran&limit=5" \ -H "X-Api-Key: YOUR_API_KEY" ``` Response: array of `{code, name, city, country}`. Results are concrete airport codes. Fare searches accept those codes plus official metro IATA codes such as PAR, LON, or MIL; itinerary segments always identify the concrete airports used. If a code also identifies a concrete airport, the concrete airport meaning takes precedence. ## Errors All errors return a consistent JSON envelope: ``` {"error": {"type": "invalid_request", "code": "invalid_airport_code", "message": "origin must be a supported 3-letter airport or metro IATA code.", "field": "origin"}} ``` `type` is the category ("invalid_request", "auth_error", "billing_error", "not_found", or "upstream_error"), `code` is machine-readable, `message` is human-readable, and `field` names the offending request field when applicable. Status codes: 400 invalid request, 401 missing/invalid API key, 402 billing required or blocked, 404 ignav_id or itinerary not found, 424 upstream error (safe to retry), 429 `monthly_spend_limit_reached` (do not retry until the limit or billing cycle changes), and 503 `billing_period_unavailable` (retry shortly). Failed requests are never billed. ## Pricing $2.00 per 1,000 successful requests. The first 1,000 requests are a one-time free allowance and do not reset monthly. Only successful (HTTP 200) requests are billed — a request is a one-way, round-trip, or flexible fare search, a booking link lookup, or an airport search. No provider-imposed request throttle and no monthly minimums. Details: https://ignav.com/pricing