Flight object
POST /v1/raim/route, POST /v1/notams/route, POST /v1/weather/route and POST /v1/airspace/route take the same flight object, so one object can go to all four. Each reads what it needs from it and ignores the rest of it. Beside it, each takes its own options, listed with the endpoint. A field that is neither is refused with 400 unknown_field.
The flight as waypoints:
{ "waypoints": [
{ "id": "KJFK", "lat": 40.6398, "lon": -73.7789, "alt_ft": 13, "codes": ["KJFK"], "phase": "terminal" },
{ "id": "TOC", "lat": 41.3, "lon": -70.0, "fl": 350, "phase": "enroute" },
{ "id": "4460N", "lat": 44.0, "lon": -60.0, "fl": 350, "phase": "oceanic" },
{ "lat": 50.0, "lon": -40.0, "fl": 350 },
{ "lat": 52.0, "lon": -20.0, "fl": 370 },
{ "id": "TOD", "lat": 51.6, "lon": -3.5, "fl": 370, "phase": "enroute" },
{ "id": "EGLL", "lat": 51.4706, "lon": -0.4619, "alt_ft": 83, "codes": ["EGLL"], "phase": "approach" } ],
"departure": "2026-09-24T08:00:00Z", "speed_kt": 480 }
waypoints(at least 2; the RAIM route check takes up to 500, the NOTAM and weather routes up to 200): each needslatandlon. Optional:id(a name;labelis read asid),time(RFC 3339), one ofalt_m,alt_ftorfl(flight level: 350 for FL350),codes(aerodrome identifiers at the point), and the RAIM alert limit,phaseorhal_nm(see RAIM prediction).departure: the time of the first waypoint when it has none.speed_kt(up to 2000): ground speed for the waypoints without a time.
The flight as filed:
{ "route": "LDZA DCT 4448N01552E DCT LDSP", "departure": "2026-09-24T07:00:00Z", "speed_kt": 250, "cruise_fl": 150 }
route(up to 2,000 characters),departure,speed_kt, the cruise level as one ofcruise_fl(0 to 650) orcruise_alt_m(-500 to 20,000), and for RAIMphase(defaultauto) orhal_nm.- The route is resolved once, the way
GET /v1/routes/resolveresolves it, with the AIRAC cycle in force atdeparture(the NOTAM route without a departure: atfrom, else now). Its airports are aerodromes, as if their code were incodes. Every answer to a route string addsresolved_route:route,points[],notes[],nav_data. A point that cannot be placed is 422route_unresolvedwithunresolved[], on all three. routeandwaypointstogether are 400bad_request("Give route or waypoints, not both."); neither is 400bad_requesttoo.cruise_fl,cruise_alt_m,phaseandhal_nmat the top level go withrouteonly: with waypoints they are 400unknown_field, because each waypoint carries its own level and alert limit.
What each endpoint reads:
- RAIM route check: positions, times,
departure,speed_ktand the alert limits. Levels are in metres, soalt_ftandflare converted (FL x 100 ft x 0.3048: FL350 is 10,668 m). A route string: the departure and destination airports at field elevation, every other point at the cruise level (without one, at its own elevation), phases from its airports unlessphaseorhal_nmis given. - NOTAM route: positions,
idandcodes. Times only for the window (seePOST /v1/notams/route); levels and alert limits are not used. - Weather route: positions, times, levels as given,
codes,departureandspeed_kt; the service times and levels the flight itself. A route string with a cruise level climbs from the departure airport's field elevation at 250 ft a NM to a top of climb (TOC), flies the cruise level, and descends on a 3 degree path (318 ft a NM) from a top of descent (TOD) to the destination's field elevation;TOCandTODare added as points (they show among the fixes), and a route too short to level off gets oneTOCwhere the climb meets the descent. A route string that starts or ends away from an airport is at the cruise level there. Without a cruise level no point has a level, so no hazard is left out by level (two field elevations alone would fly the whole route near the ground). Waypoints are flown as given: give your own top of climb and top of descent.
The flight object is checked before anything is sent, the same way on all three. A field it does not document is 400 unknown_field, naming the waypoint and the field; a value that cannot be right is 422 validation with errors per field. Waypoints are counted from 0. Times are RFC 3339; numbers are JSON numbers ("51.47" is refused).
{ "error": "unknown_field", "message": "Waypoint 1 (EGLL): unknown field eta. A waypoint takes id, lat, lon, time, alt_m, alt_ft, fl, codes, phase, hal_nm (label is read as id). See https://bravoecho.ai/llms-full.txt for the documented request." }
{ "error": "validation", "message": "waypoint 0 (KJFK): give one of alt_m, alt_ft and fl. (and 1 more error)",
"errors": { "waypoints.0.alt_m": ["waypoint 0 (KJFK): give one of alt_m, alt_ft and fl."],
"waypoints.1.lat": ["waypoint 1 (EGLL): lat must be a number from -90 to 90."] } }
One flight, three answers. The route string above sent to the three endpoints; each answer leads with summary:
for e in raim notams weather; do
curl -s https://api.bravoecho.ai/v1/$e/route \
-H "Authorization: Bearer $BRAVOECHO_KEY" -H "Content-Type: application/json" \
-d @flight.json | jq -r .summary
done
RAIM is available along the whole route at the planned times.
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.
135 NM, 24 07:00Z to 24 07:32Z. No hazard in force meets the corridor at the aircraft's time and level. departure LDZA: METAR VFR, TAF worst VFR around 07:00Z. destination LDSP: METAR VFR, TAF worst VFR around 07:32Z. Collection has 1 gap(s) in the period: see meta.gaps.