API reference

NOTAMs

Beta

The NOTAM archive: every NOTAM the FAA NOTAM Management Service distributes (US domestic, FDC, military and the international feed, worldwide), collected every few minutes since 2026-08-12, kept as append-only versions. Answers describe a time and say so; nothing is hidden behind a 200. All times RFC 3339 UTC.

GET /v1/notams

At least one filter is required. Query parameters:

  • location: domestic or ICAO identifiers, comma separated (KJFK,JFK,EGLL). Either form matches.
  • fir: FIR identifiers (EGTT,KZNY). Matches NOTAMs affecting the FIR or addressed to it.
  • bbox: west,south,east,north in degrees.
  • lat, lon, radius_nm: within a radius (up to 1000 NM) of a point.
  • classification: DOM, INTL, MIL, FDC, LMIL, comma separated.
  • category: runway, taxiway, aerodrome, lighting, obstacle, navaid, airspace, warning, procedure, service, other (our grouping of the Q-code, with the FAA keyword as fallback).
  • number: exact NOTAM number (A1045/26, 06/048).
  • q: substring over text, number and locations.
  • from, to: an in-force window. Returns NOTAMs effective at any point of it, reaching back into expired ones (bounded by when collection started). An estimated end never excludes a NOTAM.
  • active: default true, the FAA's live set (distributed, not necessarily in force yet; use a window for "in force now"). false includes cancelled and expired.
  • as_of: replay the archive as it was known at that instant.
  • include: geometry (the FAA's own geometry, GeoJSON), area (the affected area: FAA polygon, else the area read out of the text, else the radius circle; area_source says which, area_km2 its size), raw (ICAO and domestic renderings as received).
  • collapse: default true. The same notice issued under two numbers (domestic 06/048 and international A1045/26) is one entry with also_issued_as.
  • cursor, limit: newest first, limit up to 500, default 100. meta.next_cursor continues.
curl -H "Authorization: Bearer $BRAVOECHO_KEY" \
  "https://api.bravoecho.ai/v1/notams?location=EGLL&from=2026-09-20T06:00:00Z&to=2026-09-20T12:00:00Z&include=area"

Response: notams[] with nms_id, number, classification, category, title (our plain reading of the Q-code, null when there is nothing trustworthy to say), unusable, type (N new, R replaces, C cancels another NOTAM), location, icao_location, affected_fir, is_active, issued_at, effective_start, effective_end, estimated, cancelled_at, schedule (the raw D) field), selection_code, traffic, purpose, scope, lower_limit, upper_limit, minimum_fl, maximum_fl, coordinates, radius_nm, text, faa_last_updated, observed_at, version_count, and the included blocks. meta: total, returned, truncated, next_cursor, duplicates_collapsed, window (semantic is active, in_force or all), and for anything about the past as_of (archive_start, before_archive) and gaps (unrecovered collection holes before the period, with from, to, status). Read meta.gaps before trusting history: the upstream feed reaches back 24 hours, so an outage longer than that is a permanent hole and is listed.

GET /v1/notams/{nms_id}

Everything held about one NOTAM: the fields above plus raw.icao, raw.domestic, raw.aixm (as received, never reformatted), schedule_decoded (the D) field read into kind, summary and entries; display only, it never removes a NOTAM from a result), the text-derived geometry, and provenance (source, first_seen_at, last_seen_at). 404 when the id is not in the archive.

GET /v1/notams/{nms_id}/history

Every observed version, oldest first: version_id, faa_last_updated, observed_at, source, content_hash, the lifecycle fields, text, and changed_from_previous (which of text, effective_start, effective_end, cancellation_date, type changed).

POST /v1/notams/route

NOTAMs along a flight. The flight is the flight object (see Flight object): waypoints or a route string, with departure and speed_kt. The NOTAM service reads each point's position, name (id, or label) and codes.

{ "route": "LDZA DCT 4448N01552E DCT LDSP", "departure": "2026-09-24T07:00:00Z", "speed_kt": 250,
  "half_width_nm": 5, "terminal_radius_nm": 10,     // defaults
  "fl_from": 100, "fl_to": 350,                     // optional; only a clean three-digit Q-line pair can exclude a NOTAM
  "classifications": [], "categories": [], "q": "",
  "include_area": false, "include_geometry": false, "include_raw": false, "collapse": true, "limit": 500 }

The window: from and to when either is given; a NOTAM in force at any point of it matches, and one of them alone is an instant. Without them, the flight's own window: from the first waypoint's time (or departure) to the last waypoint's time, or else to the last time known plus the rest of the route at speed_kt along the great circles. A flight that starts at a known time but cannot reach its arrival is 422 validation on speed_kt; one with times but no start, on departure. A flight with no time at all asks for the live set (distributed, not necessarily in force yet). meta.window says which window was used.

The corridor is the great-circle line buffered sideways plus a circle around each waypoint. NOTAMs match by area, by aerodrome code (codes on a waypoint, and the airports of a route string), and through a FIR channel: FIR-wide notices addressed to the FIRs the corridor touched. Each NOTAM carries placement: crosses (chainage_nm where the area is entered, span_end_nm where it is left), abeam (chainage_nm of the nearest point, offset_nm off track), aerodrome (chainage of the fix), fir, or unplaced. meta.route: length_nm, waypoint_chainage[], firs[], fir_section (matched_by_affected_fir or unavailable: a route through airspace where nothing else matched still misses its FIR notices), placements counts. Same meta.gaps rule as search. When there are more matches than limit, the answer keeps the notices crossing the route first, then those at its aerodromes, then the ones abeam, nearest first, then FIR-wide ones, so the same request returns the same notices; meta.total counts every match.

The answer is summary, then the service's notams and meta as they are, and resolved_route for a route string. summary is the answer in one sentence: how many NOTAMs, in force when, where they sit, and the two caveats when they apply (the corridor touched no FIR in the archive; the answer stopped at limit before every match, meta.truncated). It counts the notices returned, a notice issued under two numbers once. Live, the flight above:

{ "summary": "1 NOTAM along the route, in force 24 Sep 07:00Z to 07:32Z: 1 crossing the corridor, 0 abeam, 0 at the route's aerodromes, 0 FIR-wide.",
  "notams": [ { "number": "A3710/26", "icao_location": "LQSB", "category": "airspace", "title": "Danger area activated",
                "placement": "crosses", "chainage_nm": 55.76438613588303, "span_end_nm": 57.76362309611289, ... } ],
  "meta": { "window": { "from": "2026-09-24T07:00:00Z", "to": "2026-09-24T07:32:27Z", "semantic": "in_force" },
            "route": { "length_nm": 135.2, "firs": ["LQSB"], "fir_section": "matched_by_affected_fir", ... }, ... },
  "resolved_route": { "route": "LDZA 4448N01552E LDSP", "notes": [], ... } }

Other live summaries: from alone, "1 NOTAM along the route, in force at 24 Sep 12:00Z: ..."; waypoints without times, "2 NOTAMs along the route, in the live set: 2 crossing the corridor, 0 abeam, 0 at the route's aerodromes, 0 FIR-wide."; a route whose corridor met no FIR, "... 0 FIR-wide. The corridor touched no FIR in the archive, so FIR-wide notices for this route are missing."

GET /v1/locations/{id}

The FAA location reference row for a domestic or ICAO identifier: location_id, icao_id, description, state_text, center_text and the full payload. GET /v1/notams/categories lists the category slugs.