API · v1

Flight Tracking API

Real-time flight tracking in a single request: live status, schedule, route and aircraft for any flight worldwide, in a clean, well-structured JSON format.

A clean JSON API for flights, airports and live airspace. /airline returns full schedule, route, aircraft and status; /track the live position of an airborne flight; /schedules the projected timetable for a flight over the coming days; /airport airport lookup, search and nearest-to-a-coordinate; /airspace every aircraft in the air in an area; /route the route a flight flies. Every request takes an API key; each call costs one credit.

Base URL & authentication

https://api.flightnerve.com

Your API key is required on every request, passed as the first path segment:

/airline/<api_key>?num=...&name=...&date=...
/track/<api_key>?num=...&name=...&date=...
Each call is counted against your key's credits, so you can see exactly what you use in the console. A missing or inactive key returns 401; an exhausted quota returns 429. Create a free key →

Response format

Every tracking response is a JSON array of four objects (departure, arrival, aircraft and status) in that order. Times are given both as a human string local to the airport and as an ISO-8601 timestamp with the airport's UTC offset. Fields that are not published are returned as null, never omitted, so the shape is always stable.

Multi-leg without depap: the response is instead an array of legs ([ [departure, arrival, aircraft, status], [ … ] ]), one entry per leg. Detect it by checking whether the first element is an array.

Flight status

GET/airline/<api_key>

Full schedule, route, aircraft and status for a single flight on a given date.

Query parameters

ParamRequiredDescription
numrequiredFlight number, digits only (e.g. 72 for EK72).
namerequiredAirline code, IATA (EK) or ICAO (UAE).
dateoptionalTarget date, YYYYMMDD. Defaults to the active/next instance.
depapoptionalDeparture airport IATA. Disambiguates when a flight number departs from different origins, including a multi-leg flight: selects the leg departing this airport.
Some flight numbers cover more than one leg. For example EK205 flies DXB → MXP → JFK. Identify a leg by its departure airport: depap=DXB returns DXB → MXP, depap=MXP returns MXP → JFK. Called without depap, a multi-leg flight returns all legs (an array of leg objects, see below) and is billed one credit per leg.

Example request

curl "https://api.flightnerve.com/airline/YOUR_KEY?num=72&name=EK&date=20260720"
const res = await fetch("https://api.flightnerve.com/airline/YOUR_KEY?num=72&name=EK&date=20260720");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/airline/YOUR_KEY?num=72&name=EK&date=20260720")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/airline/YOUR_KEY?num=72&name=EK&date=20260720");
$data = json_decode($res, true);
print_r($data);

Example response

[
  { "departure": {
      "offGroundTime": null, "outGateTime": null, "gate": null,
      "departureDateTime": "2026-07-20T11:30:00+02:00",
      "duration": "7 hr",
      "airport": "Charles de Gaulle", "airportCity": "Paris",
      "airportCode": "CDG", "airportCountryCode": "FR",
      "airportSlug": "CDG-Paris-France",
      "scheduledTime": "11:20, Jul 20", "estimatedTime": "11:30, Jul 20",
      "terminal": "2C"
  }},
  { "arrival": {
      "timeRemaining": null, "onGroundTime": null, "inGateTime": null,
      "gate": null, "baggage": null,
      "arrivalDateTime": "2026-07-20T20:20:00+04:00",
      "airport": "Dubai Int'l", "airportCity": "Dubai",
      "airportCode": "DXB", "airportCountryCode": "AE",
      "airportSlug": "DXB-Dubai-United-Arab-Emirates",
      "scheduledTime": "20:20, Jul 20", "estimatedTime": "20:20, Jul 20",
      "terminal": "3"
  }},
  { "aircraft": { "id": null, "code": "388", "name": "Airbus A380-800", "regNumber": "A6-EOA" } },
  { "status": "In Air" }
]

Response object

Elements 1 and 2 are the departure and arrival legs; the aircraft and status objects follow.

departure / arrival

FieldTypeDescription
scheduledTimestringScheduled time, local to the airport, as "HH:MM, Mon DD".
estimatedTimestringEstimated time, local.
departureDateTime
arrivalDateTime
stringISO-8601 with the airport's UTC offset.
outGateTime / inGateTimestring·nullActual gate out / in, when available.
offGroundTime
onGroundTime
string·nullActual wheels-up / wheels-down.
timeRemainingstring·nullTime to arrival while en route.
durationstring·nullScheduled block time (departure only).
airport / airportCitystringAirport name and city.
airportCodestringIATA code.
airportCountryCodestringISO-2 country code.
airportSlugstringURL-friendly CODE-City-Country.
terminal / gatestring·nullTerminal / gate, when published.
baggagestring·nullArrival baggage belt (arrival only).

aircraft

FieldTypeDescription
codestring·nullType code (e.g. 388, 77W).
namestring·nullFull type name (e.g. Airbus A380-800).
regNumberstring·nullAircraft registration (tail number, e.g. A6-EOA) of the aircraft operating the flight, identified live while it is airborne. null when the flight is not currently in the air.
idnullPresent for compatibility; not populated.

Status values

The status field reflects the live state of the flight:

ValueMeaning
ScheduledFuture flight on schedule, or an upcoming date served from the projected schedule.
In AirDeparted and currently airborne.
ArrivedLanded.
DelayedEstimated departure is 15+ minutes behind schedule (before departure).
CancelledFlight cancelled.
DivertedDiverted from its planned destination.
Other airline dispositions (e.g. Rescheduled) are passed through as reported. An upcoming date served from the projected schedule always returns Scheduled, since there is no live data yet.

Dates & data

The same endpoint answers for past, present and future dates, and the data behind it adapts:

WhenWhat you get
Today / near-termLive status and times: actual gate-out/off, estimates, gate and terminal.
PastThe final record: actual departure/arrival times and terminal status (Arrived, Cancelled, Diverted…). Completed flights are cached, so repeat lookups are instant.
UpcomingThe scheduled times. For dates beyond the published window, the recurring schedule is projected from recent history (weekday-aware) and returned as Scheduled. If a flight does not operate on the requested day, a 400 is returned.
Projected upcoming times estimate the recurring schedule and may differ by a few minutes from a later timetable change; the route, aircraft and weekday pattern are accurate.

Live position

GET/track/<api_key>

Where the aircraft is right now: latitude, longitude, altitude, ground speed and heading, plus phase and progress. An airborne flight always returns a position, and the source field tells you its quality: a real fix where there is coverage, or an estimated position (projected along the route by progress) in a coverage gap. If the flight is not airborne (a completed past flight, one that hasn't departed yet, or a future date), the array is empty ([]). You are billed one credit per position returned, so a flight that isn't in the air costs nothing.

Query parameters

ParamRequiredDescription
numrequiredFlight number, digits only (e.g. 25 for SQ25).
namerequiredAirline code, IATA (SQ) or ICAO (SIA).
dateoptionalTarget date, YYYYMMDD. Only today can be airborne; a clearly past or future date returns [] immediately.

Example request

curl "https://api.flightnerve.com/track/YOUR_KEY?num=25&name=SQ"
const res = await fetch("https://api.flightnerve.com/track/YOUR_KEY?num=25&name=SQ");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/track/YOUR_KEY?num=25&name=SQ")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/track/YOUR_KEY?num=25&name=SQ");
$data = json_decode($res, true);
print_r($data);

Example response: airborne

[
  {
    "flight": "SQ25", "callsign": "SIA25", "status": "In Air",
    "regNumber": "9V-SMR",    // aircraft tail number, when identified live
    "latitude": 59.8835, "longitude": 36.571,
    "altitude": 33000,        // feet
    "groundSpeed": 560,       // knots
    "heading": 120,           // degrees true
    "verticalSpeed": null, "onGround": false,
    "phase": "cruise",        // climb | cruise | descent
    "progress": 0.62,         // fraction of the route flown, 0..1
    "source": "live",         // live (real fix) | partner | estimated (dead-reckoned)
    "departure": { "airportCode": "FRA", "airport": "Frankfurt Int'l" },
    "arrival":   { "airportCode": "SIN", "airport": "Singapore Changi" },
    "lastUpdated": "15:16, Jul 21",       // when the position was last updated (UTC)
    "updatedAgo": "2 min ago",            // how long ago that was
    "updatedAt": "2026-07-21T15:16:47Z",  // same fix, ISO-8601 UTC
    "updatedUnix": 1784646407             // same fix, epoch seconds
  }
]

Example response: not airborne

[]   // completed, not yet departed, or a future date

Fields

FieldTypeDescription
regNumberstring·nullAircraft registration (tail number) of the aircraft flying, identified live. null if not yet identified.
latitude / longitudenumberCurrent position, decimal degrees.
altitudenumber·nullAltitude in feet.
groundSpeednumber·nullGround speed in knots.
headingnumber·nullTrack over ground, degrees true.
verticalSpeednumber·nullClimb/descent rate, ft/min, when available.
onGroundbooleanAlways false here, an airborne position.
phasestringFlight phase: climb, cruise or descent.
progressnumberFraction of the route flown, 0 to 1.
sourcestringlive (a real position fix), partner (a derived fix filling a coverage gap), or estimated (dead-reckoned along the route when no fix is available). The updated* fields are null for an estimated position.
departure / arrivalobjectOrigin and destination: airportCode (IATA) and airport name.
lastUpdatedstringWhen the position was last updated, as human UTC "HH:MM, Mon DD".
updatedAgostringHow long ago that fix was, in words (e.g. "3 min ago", "1 hr 5 min ago").
updatedAtstringThe same fix time as an ISO-8601 UTC timestamp.
updatedUnixnumberThe same fix time as epoch seconds; subtract from now for position age.
Only currently-airborne flights carry a position. For schedule, gate, terminal and times (before, during or after the flight), use /airline.

Flight schedules

GET/schedules/<api_key>

The projected timetable for a flight number over the coming days, built from FlightNerve's own accumulated operating history for that flight, not a single live lookup. Give it a flight and a start date and it returns one entry per day: the route, scheduled departure and arrival (local and UTC), block time and typical aircraft, and whether the flight is expected to operate that weekday. Useful for planning ahead when a live schedule for a future date is not yet published.

Query parameters

ParamRequiredDescription
numrequiredFlight number, digits only (e.g. 72 for EK72).
namerequiredAirline code, IATA (EK) or ICAO (UAE).
dateoptionalStart date, YYYYMMDD. Defaults to today.
daysoptionalNumber of days to project from the start date, 1 to 7. Defaults to 1.

Example request

curl "https://api.flightnerve.com/schedules/YOUR_KEY?num=72&name=EK&date=20260725&days=3"
const res = await fetch("https://api.flightnerve.com/schedules/YOUR_KEY?num=72&name=EK&date=20260725&days=3");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/schedules/YOUR_KEY?num=72&name=EK&date=20260725&days=3")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/schedules/YOUR_KEY?num=72&name=EK&date=20260725&days=3");
$data = json_decode($res, true);
print_r($data);

Example response

{
  "flight": "EK72", "callsign": "UAE72",
  "basis": "historical-pattern",
  "sampleSize": 17,            // operating days observed
  "confidence": "high",        // high · medium · low
  "days": 3,
  "schedules": [
    {
      "date": "2026-07-25", "weekday": "Sat", "operates": true,
      "legs": [
        {
          "from": "CDG", "to": "DXB",
          "fromCity": "Paris", "toCity": "Dubai",
          "departure": { "scheduledLocal": "11:20", "scheduledUTC": "2026-07-25T09:20:00Z" },
          "arrival":   { "scheduledLocal": "20:55", "scheduledUTC": "2026-07-25T16:55:00Z" },
          "blockMinutes": 455,
          "aircraft": "A388"
        }
      ]
    },
    { "date": "2026-07-26", "weekday": "Sun", "operates": true,  "legs": [ ... ] },
    { "date": "2026-07-27", "weekday": "Mon", "operates": false }   // no service that weekday
  ]
}

Fields

FieldTypeDescription
basisstringAlways "historical-pattern": projected from observed operating history, not a live schedule pull.
sampleSizenumberHow many operating days informed the projection. More samples means a firmer pattern.
confidencestringhigh (strong, consistent history), medium, or low (sparse or irregular). Treat low as indicative.
operatesbooleanWhether the flight is expected to fly that date. false means that weekday has no consistent history.
legsarrayOne object per leg, present only when operates is true. Multi-leg flight numbers return each leg in order.
blockMinutesnumberScheduled gate-to-gate time in minutes.
This is a projection from historical operating patterns, for planning ahead. For the confirmed live schedule, gate, terminal and status of a specific flight, use /airline. Billed one credit per operating day returned; days with no service are free.

Airports

GET/airport/<api_key>

Look up an airport, search by name/city, or find airports near a coordinate, from a reference of 85,000+ airports worldwide with coordinates and timezone.

Query parameters (one of)

ParamDescription
codeIATA or ICAO code; returns one airport (e.g. code=DXB or code=OMDB).
searchText match on name / city / code; returns a list (e.g. search=heathrow).
lat & lonAirports within radius km of a point, nearest first. radius optional (default 100, max 500).

Example

curl "https://api.flightnerve.com/airport/YOUR_KEY?code=DXB"
const res = await fetch("https://api.flightnerve.com/airport/YOUR_KEY?code=DXB");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/airport/YOUR_KEY?code=DXB")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/airport/YOUR_KEY?code=DXB");
$data = json_decode($res, true);
print_r($data);
{
  "iata": "DXB", "icao": "OMDB", "name": "Dubai International Airport",
  "city": "Dubai", "country": "AE", "countryName": "United Arab Emirates",
  "latitude": 25.2528, "longitude": 55.3644, "timezone": "Asia/Dubai"
}
# nearest airports to a coordinate
curl "https://api.flightnerve.com/airport/YOUR_KEY?lat=51.47&lon=-0.45&radius=40"
→ [ { "iata":"LHR", …, "distanceKm": 1.2 }, { "iata":"LCY", …, "distanceKm": 22.8 }, … ]

Live airspace

GET/airspace/<api_key>

Every aircraft in the air right now in an area: near a point, inside a bounding box, around an airport, or inbound to an airport with a live ETA. Positions refresh continuously.

Query parameters (one of)

ParamDescription
lat & lonAircraft within radius km of a point (default 100, max 500), nearest first.
bboxAircraft inside latMin,lonMin,latMax,lonMax.
airportAircraft within radius km of an airport (IATA/ICAO).
inboundAirborne aircraft routed to this airport, with distance and estimated minutes out.

Example

curl "https://api.flightnerve.com/airspace/YOUR_KEY?inbound=JFK"
const res = await fetch("https://api.flightnerve.com/airspace/YOUR_KEY?inbound=JFK");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/airspace/YOUR_KEY?inbound=JFK")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/airspace/YOUR_KEY?inbound=JFK");
$data = json_decode($res, true);
print_r($data);
{ "airport": { "iata": "JFK", "icao": "KJFK", "name": "John F. Kennedy International Airport" },
  "aircraft": [
    { "callsign": "AAL1185", "latitude": 40.7, "longitude": -73.9,
      "altitude": 4000, "groundSpeed": 210, "heading": 31, "onGround": false,
      "originCountry": "United States", "distanceKm": 9.6, "etaMinutes": 2 }, … ] }
Coverage follows live-signal reception: excellent over land and busy airspace, with gaps over remote oceans. Each aircraft carries updatedUnix (epoch of its last position fix).

Routes

GET/route/<api_key>

Answers four route questions from FlightNerve's own accumulated operating history — which flights fly a route, an airline's whole network, an airport's destinations, or one flight's route — each enriched with the aircraft types actually seen and any codeshare flight numbers. No external call; one credit per query.

Query parameters (one of)

ParamReturns
from & toRoute detail: every flight observed operating A→B — airline, flight number, aircraft, codeshares, days observed — plus the route distance.
airlineAirline network: every route the airline operates (IATA or ICAO code), with flight numbers and aircraft per route.
fromDestinations served from an airport, each with the airlines and flight numbers on it.
toOrigins that reach an airport, likewise.
num & nameA single flight → its origin, destination, stops, aircraft and codeshares.

Example — route detail

curl "https://api.flightnerve.com/route/YOUR_KEY?from=DXB&to=LHR"
const res = await fetch("https://api.flightnerve.com/route/YOUR_KEY?from=DXB&to=LHR");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/route/YOUR_KEY?from=DXB&to=LHR")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/route/YOUR_KEY?from=DXB&to=LHR");
$data = json_decode($res, true);
print_r($data);
{ "from": { "iata":"DXB", "city":"Dubai", … },
  "to":   { "iata":"LHR", "city":"London", … },
  "distanceKm": 5498,
  "airlines": ["EK"], "operatorCount": 1, "flightCount": 3,
  "flights": [
    { "flight":"EK1", "airline":"EK", "airlineName":"Emirates",
      "aircraft":["A388","B38M"], "codeshares":["GA8887"],
      "daysObserved":14, "lastSeen":"2026-07-25" }, … ] }

Example — airline network

curl "https://api.flightnerve.com/route/YOUR_KEY?airline=EK"
→ { "airline":"EK", "airlineName":"Emirates", "routeCount":109,
      "routes":[ { "from":{"iata":"DXB",…}, "to":{"iata":"JFK",…},
                   "flights":["EK201"], "aircraft":["A388"], "daysObserved":15 }, … ] }
Built from operations FlightNerve has actually observed, so coverage grows over time and is richest on well-trafficked routes. Gives origin/destination, aircraft and codeshares — not scheduled times; for those use /schedules (future timetable) or /airline (live).

Tracked flights

GET/watch/<api_key>

Keep a personal watchlist of flights. Each is monitored continuously and returns three arrival anchors: the scheduled time, our own FlightNerve Estimated Arrival, and the live observed arrival, plus cancelled / diverted / arrived flags.

List tracked flights

curl "https://api.flightnerve.com/watch/YOUR_KEY"
const res = await fetch("https://api.flightnerve.com/watch/YOUR_KEY");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/watch/YOUR_KEY")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/watch/YOUR_KEY");
$data = json_decode($res, true);
print_r($data);
{ "success": true, "tracked": [
  { "flight": "EK072", "day": "20260722", "leg": null,
    "route": { "from": "OMDB", "to": "VTBS" },
    "status": "active", "flags": [],
    "arrivals": {
      "scheduled_utc":    "2026-07-22T20:43:00Z",
      "fn_estimated_utc": "2026-07-22T20:41:12Z",
      "live_utc":         "2026-07-22T20:42:00Z" },
    "fn_source": "blend",
    "live": { "phase": "cruise", "progress": 0.41, "dist_rem_km": 3074 } }, … ] }

Add or remove a flight

POST/watch/<api_key>
Body fieldDescription
flightFlight number, e.g. EK072. Required to add.
dateYYYYMMDD, the day to track. Defaults to today.
legOptional DEP-ARR (ICAO) to pin one leg of a multi-leg flight.
actionSet to remove to stop tracking (with id or flight).
curl -X POST "https://api.flightnerve.com/watch/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"flight": "EK072", "date": "20260722"}'
const res = await fetch("https://api.flightnerve.com/watch/YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"flight": "EK072", "date": "20260722"})
});
const data = await res.json();
console.log(data);
import requests

r = requests.post("https://api.flightnerve.com/watch/YOUR_KEY",
                  json={'flight': 'EK072', 'date': '20260722'})
print(r.json())
<?php
$ch = curl_init("https://api.flightnerve.com/watch/YOUR_KEY");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"flight": "EK072", "date": "20260722"}');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data);

Stop tracking — same endpoint with action: "remove":

curl -X POST "https://api.flightnerve.com/watch/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "remove", "id": 42}'
const res = await fetch("https://api.flightnerve.com/watch/YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"action": "remove", "id": 42})
});
const data = await res.json();
console.log(data);
import requests

r = requests.post("https://api.flightnerve.com/watch/YOUR_KEY",
                  json={'action': 'remove', 'id': 42})
print(r.json())
<?php
$ch = curl_init("https://api.flightnerve.com/watch/YOUR_KEY");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"action": "remove", "id": 42}');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data);

Leg options

curl "https://api.flightnerve.com/watch/YOUR_KEY/legs?flight=EK072"
→ { "success":true, "flight":"EK072",
    "legs":[ { "leg":"OMDB-VTBS", "dep_icao":"OMDB", "arr_icao":"VTBS" }, … ] }
FlightNerve Estimated Arrival is our own arrival prediction. Far from the destination it follows the flight's planned duration; as the aircraft nears arrival it switches to our live estimate, and it always defers to live data when a flight is running early, late or diverted. Cancelled flights carry a cancelled flag and no estimate; flights that have arrived or been cancelled stop refreshing automatically.

Create a flight monitor

POST/monitor/<api_key>

Start monitoring a specific flight on a date and attach it to your account. Give it a flight and date, optionally describe which changes you want to be informed of and how sensitive the alerts should be. Every qualifying change is pushed to your webhook and recorded under Alerts.

The response returns a stable monitoring_id (e.g. mon_fbba35cd573ca081). Store it: it identifies this exact monitor, is echoed in every webhook we send for it, appears on each alert, and is the same if you re-add the same flight/date — so you can correlate incoming alerts to what you set up without parsing flight numbers.

Body

Body fieldDescription
flightFlight number, e.g. EK72. (Or send name+num, e.g. "name":"EK","num":72.) Required.
dateYYYYMMDD, the day to monitor. Defaults to today.
legOptional DEP-ARR (ICAO) to pin one leg of a multi-leg flight.
monitorOptional alert config (below). Omit to monitor every event at the default 15-minute sensitivity.
actionSet to remove to stop monitoring (with id, or flight+date).

The monitor config

FieldDescription
sensitivity_minMinutes of change required to (re)fire a time alert. Default 15. A departure/arrival estimate must move at least this much from the value we last alerted you on to fire again — so a drift from 12 to 18 minutes late (6 min) will not re-alert.
eventsObject toggling each event. Any event you don't list stays on; set one false to mute it.

Events you can monitor:

EventFires when…
departurethe flight actually departs (off-blocks).
departure_latethe departure estimate moves later (delay), beyond the sensitivity.
departure_earlythe departure estimate moves earlier.
arrival_latethe arrival estimate moves later (delay).
arrival_earlythe arrival estimate moves earlier.
gatea departure or arrival gate is assigned or changed.
terminala terminal is assigned or changed.
baggagethe arrival baggage belt is assigned or changed.
schedule_changethe published scheduled time changes.
cancelled / diverted / landedthe flight is cancelled, diverted, or lands.

Example

curl -X POST "https://api.flightnerve.com/monitor/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"flight": "EK72", "date": "20260726", "monitor": {"sensitivity_min": 20, "events": {"departure_early": false, "gate": false}}}'
const res = await fetch("https://api.flightnerve.com/monitor/YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"flight": "EK72", "date": "20260726", "monitor": {"sensitivity_min": 20, "events": {"departure_early": false, "gate": false}}})
});
const data = await res.json();
console.log(data);
import requests

r = requests.post("https://api.flightnerve.com/monitor/YOUR_KEY",
                  json={'flight': 'EK72', 'date': '20260726', 'monitor': {'sensitivity_min': 20, 'events': {'departure_early': False, 'gate': False}}})
print(r.json())
<?php
$ch = curl_init("https://api.flightnerve.com/monitor/YOUR_KEY");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"flight": "EK72", "date": "20260726", "monitor": {"sensitivity_min": 20, "events": {"departure_early": false, "gate": false}}}');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data);
{ "success": true, "id": 115, "monitoring_id": "mon_fbba35cd573ca081",
    "flight": "EK72", "day": "20260726", "source": "api",
    "webhook": "https://your-server.example/hooks/fn",
    "monitor": { "sensitivity_min": 20, "events": { "departure_early": false, "gate": false } } }

Webhooks

POST/webhook/<api_key>

Set one webhook URL per account. Whenever a monitored flight changes, FlightNerve POSTs a JSON object to your URL. Every alert is also stored under Alerts with its delivery status, so nothing is lost if your endpoint is briefly unreachable.

Set / read your webhook

curl -X POST "https://api.flightnerve.com/webhook/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-server.example/hooks/fn"}'
const res = await fetch("https://api.flightnerve.com/webhook/YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"url": "https://your-server.example/hooks/fn"})
});
const data = await res.json();
console.log(data);
import requests

r = requests.post("https://api.flightnerve.com/webhook/YOUR_KEY",
                  json={'url': 'https://your-server.example/hooks/fn'})
print(r.json())
<?php
$ch = curl_init("https://api.flightnerve.com/webhook/YOUR_KEY");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"url": "https://your-server.example/hooks/fn"}');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data);

Read your current webhook:

curl "https://api.flightnerve.com/webhook/YOUR_KEY"
const res = await fetch("https://api.flightnerve.com/webhook/YOUR_KEY");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/webhook/YOUR_KEY")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/webhook/YOUR_KEY");
$data = json_decode($res, true);
print_r($data);

Test it: POST {"test": true, "url": "…"} to /webhook/<api_key> and we deliver a sample alert to that URL and tell you whether it replied: { "delivered": true, "code": 200 }. The console has a Test button that does exactly this.

Webhook payload

Your endpoint receives a POST with Content-Type: application/json and this body. Respond with any 2xx to acknowledge.

{
  "event": "flightnerve.alert",
  "alert_id": 481,
  "monitoring_id": "mon_fbba35cd573ca081",
  "flight": "EK72",
  "date": "20260726",
  "leg": "",
  "route": "DXB-MUC",
  "source": "api",
  "created_utc": "2026-07-26T13:58:04Z",
  "monitor": { "sensitivity_min": 20, "events": { "gate": false } },
  "changes": [
    { "field": "arrival_estimate", "type": "delayed",
      "from": "2026-07-26T14:00:00Z", "to": "2026-07-26T14:25:00Z",
      "delta_min": 25, "to_local": "16:25" }
  ]
}
FieldDescription
eventAlways flightnerve.alert.
alert_idStable id of this alert (also under /alerts).
monitoring_idThe monitor this alert belongs to — the same monitoring_id returned when you created it. Use it to route the alert on your side.
flight / date / leg / routeThe monitored flight this alert is for.
sourceapi if the monitor was created via the API, else console.
changesOne or more change objects. Each carries a field, a type (delayed, earlier, departed, assigned, changed, cancelled, landed, diverted, schedule_change), the from/to values, and for time changes a delta_min (minutes vs schedule) and to_local (local HH:MM).
Deliveries are best-effort with an 8-second timeout. The result (delivered / failed + HTTP code) is attached to each alert (webhook_status, webhook_code) and shown in the console, so you can always reconcile against /alerts.

Monitored flights (live board)

GET/monitored/<api_key>

One call for the live board of everything on your watchlist that still matters: every flight that is scheduled or in the air, plus any that landed within the last hour. Flights that landed more than an hour ago drop off automatically. Each entry carries the final schedule, times, gate, terminal, baggage belt, status, and a live position when the aircraft is airborne with a fix.

Example

curl "https://api.flightnerve.com/monitored/YOUR_KEY"
const res = await fetch("https://api.flightnerve.com/monitored/YOUR_KEY");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/monitored/YOUR_KEY")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/monitored/YOUR_KEY");
$data = json_decode($res, true);
print_r($data);
{ "success": true, "count": 12, "flights": [
  { "flight": "EK216", "day": "20260723", "callsign": "UAE216",
    "status": "In Air", "regNumber": "A6-EOA",
    "codeshares": ["QF8016", "AF3634"],
    "route": { "from": "LAX", "to": "DXB", "fromCity": "Los Angeles", "toCity": "Dubai" },
    "departure": { "scheduled": "2026-07-23T23:40:00Z", "actual": null,
                   "estimated": "2026-07-24T00:52:00Z", "delayMinutes": 72,
                   "terminal": "B", "gate": null },
    "arrival":   { "scheduled": "2026-07-24T16:30:00Z", "estimated": "2026-07-24T17:51:00Z",
                   "terminal": "3", "gate": "C1", "baggage": "5" },
    "position":  { "latitude": 50.1, "longitude": 7.4, "altitude": 36000,
                   "groundSpeed": 470, "heading": 283,
                   "phase": "cruise", "progress": 0.53, "source": "live" } }, … ] }

Fields

FieldDescription
statusScheduled, In Air, Arrived, Cancelled or Diverted.
regNumberAircraft registration (tail number) of the aircraft flying, identified live while airborne; null otherwise.
codesharesOther flight numbers the same physical flight is marketed under (e.g. ["QF8016","AF3634"]). Empty when none are known for the flight.
departure / arrivalscheduled, actual/estimated (ISO-8601 UTC), delayMinutes, terminal, gate; arrival also carries baggage (belt).
positionPresent only while airborne with a fix: latitude, longitude, altitude (ft), groundSpeed (kt), heading, phase, progress (0 to 1), source (live or partner). For an estimated position in a coverage gap, call /track.
All times here are the final FlightNerve values (identical to what /airline returns per flight). Use this to render an operations board with one request instead of one per flight.

Alerts

GET/alerts/<api_key>

Every change detected on your monitored flights, newest first: a departure or arrival running early or late, a gate, terminal or baggage belt assigned or changed, a schedule revision, a departure, a landing, a cancellation or a diversion. Each alert names the flight and its date and lists exactly which fields changed.

Example

curl "https://api.flightnerve.com/alerts/YOUR_KEY?unread=1"
const res = await fetch("https://api.flightnerve.com/alerts/YOUR_KEY?unread=1");
const data = await res.json();
console.log(data);
import requests

r = requests.get("https://api.flightnerve.com/alerts/YOUR_KEY?unread=1")
print(r.json())
<?php
$res  = file_get_contents("https://api.flightnerve.com/alerts/YOUR_KEY?unread=1");
$data = json_decode($res, true);
print_r($data);
{ "success": true, "unread": 2, "alerts": [
  { "id": 41, "flight": "LH766", "day": "20260723", "route": "MUC-BOM",
    "created": 1784822100, "read": 0,
    "changes": [
      { "field": "arrival_estimate", "type": "delayed",
        "to": "2026-07-24T12:51:00Z", "to_local": "18:21", "delta_min": 34 },
      { "field": "arrival_gate", "type": "assigned", "to": "C1" } ] }, … ] }

Mark read

curl -X POST "https://api.flightnerve.com/alerts/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": [41, 40]}'
const res = await fetch("https://api.flightnerve.com/alerts/YOUR_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"ids": [41, 40]})
});
const data = await res.json();
console.log(data);
import requests

r = requests.post("https://api.flightnerve.com/alerts/YOUR_KEY",
                  json={'ids': [41, 40]})
print(r.json())
<?php
$ch = curl_init("https://api.flightnerve.com/alerts/YOUR_KEY");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"ids": [41, 40]}');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
print_r($data);

Omit ids to mark every alert read.

Change fieldMeaning
departure_estimate / arrival_estimatePredicted time moved. to_local is the new local time; delta_min is +late / -early versus schedule.
departure / statusDeparted, landed, cancelled or diverted.
departure_gate / arrival_gate / *_terminal / arrival_baggageGate, terminal or baggage belt assigned or changed.
departure_scheduled / arrival_scheduledThe scheduled time itself was revised.
Query ?unread=1 for new alerts only. This collection is the backbone for delivery by email or webhook.

Health

GET/health
{ "status": "ok", "service": "flightnerve", "ts": 1784540431 }

Errors

Errors return a small JSON object with a message and success: false, and an appropriate HTTP code.

CodeWhen
400Missing num/name, the flight/date could not be resolved, or the flight does not operate on the requested date.
401Missing, unknown or inactive API key.
429API key quota exceeded.
404Unknown path.
{ "message": "Either your date is wrong or airline code is wrong. Please verify the flight number and date.", "success": false }

{ "message": "No scheduled flight found for this flight number on that date.", "success": false }

Notes & limits

Live results are cached briefly (~60 s per flight) and completed past flights are cached permanently, so repeat lookups are near-instant.

Keep request volume proportional to real user searches rather than continuous polling. Fields that are not published are returned as null, never omitted, so the response shape is always stable. Typical latency ~0.8 s. CORS is open (Access-Control-Allow-Origin: *).

© FlightNerve · Flight Tracking API v1Console