API reference
Base URL https://api.noxdren.com · auth header X-API-Key · all
endpoints under /v1. The full machine-readable schema is always live at
/openapi.json.
Units. Battery state and threshold fields, including initial_pct,
rth_threshold_pct, battery_start_pct, battery_end_pct, and
final_battery_pct, are expressed in percentage points on a nominal 0 to 100
battery scale. Battery-consumption and RTH-cost fields are also expressed in
battery percentage points but may exceed 100 when a route is infeasible.
Return-margin fields may be negative when the predicted battery is
insufficient for the modeled return. Durations are expressed in seconds,
distances in meters, speeds in meters per second, and temperatures in degrees
Celsius. The API predicts battery consumption, return-home margin, duration,
and mission feasibility; it does not compute or return physical energy in
watt-hours.
Validation status. Automated tests verify implementation behavior, contract consistency, and reproducibility; they do not establish real-world prediction accuracy. Noxdren does not currently publish a field-validated accuracy claim. Real-world performance depends on the aircraft profile, battery condition, payload, mission geometry, environmental conditions, terrain data, and input quality. Integrators should validate performance against representative flight data for their aircraft and use case before operational reliance. Noxdren outputs are advisory and must not serve as the sole authority for safety-critical flight decisions.
Health
GET /v1/health
Liveness. Public (no key). → { "ok": true, "server_version", "engine_version" }
GET /v1/version
→ { "server_version", "engine_version" }
Drones (engine: rangeiq_plus)
GET /v1/drones
List the drone catalog. → { "ok": true, "drones": [ … ], "request_id" }
Each drone: key, cruise_speed_mps, baseline_flight_time_min,
battery_reserve_frac, max_payload_g, hover_drain_pct_per_min, … .
GET /v1/drones/{key}
One drone by catalog key. 404 NOT_FOUND if unknown. → { "ok", "drone", "request_id" }
RangeIQ — range rings (engine: rangeiq)
POST /v1/rangeiq/analyze
Battery-aware range rings around a launch point.
Request (JSON) — key fields:
| field | type | default | notes |
|---|---|---|---|
user_lat, user_lon | number | — | required; launch point |
selected_drone_key | string | "" | catalog key |
unit_mode | string | metric | metric or imperial |
wind_speed, gust_speed | number | 0 | m/s (or mph if imperial) |
wind_direction | number | 0 | degrees |
temperature | number | 20 | °C (metric) / °F (imperial) |
humidity | number | 50 | % |
altitude | number | 120 | AGL m |
initial_battery | number | 85 | % |
hover_time_min | number | 0 | minutes |
use_payload, payload_weight | bool / number | false / 0 | grams |
Response → { "ok", "engine_version", "result": { "center", "rings": [ { "battery_threshold_pct", "label", "color", "polygon": [{lat,lon}…] } ], "oneway_ring", "physics": {…} }, "request_id" }.
RangeIQ+ — mission analysis (engine: rangeiq_plus)
POST /v1/missions/analyze-geometry (JSON)
Analyze a mission given inline waypoints — no file needed.
Request — abbreviated schema example (shape illustration only, not an
accuracy-validation request). The two drone values shown are the DJI Mini 4
Pro's public manufacturer specifications as served by the catalog; they are
not measured or validated Noxdren calibration values:
{
"mission": {
"waypoints": [
{ "lat": 37.5, "lon": -122.3, "altitude_m": 80, "hover_time_s": 0 }
],
"source_format": "geometry"
},
"home": { "lat": 37.5, "lon": -122.3 },
"drone": { "key": "mini4pro", "cruise_speed_mps": 6.71, "baseline_flight_time_min": 34.0 },
"battery": { "initial_pct": 100, "rth_threshold_pct": 25, "cycles": 0 },
"weather": { "wind_speed_mps": 6, "wind_dir_deg": 270, "temp_c": 20, "humidity_pct": 50 }
}
For production analysis, do not hand-copy profile fields: fetch the aircraft's
complete catalog entry from GET /v1/drones/{key} (response shape
{ "ok", "drone", "request_id" }) and pass the drone object through
unchanged. Generic pseudocode (client stands for any HTTP client):
# pseudocode — substitute your HTTP client of choice
profile = client.get("/v1/drones/mini4pro").json()["drone"]
body["drone"] = profile # complete catalog profile, passed through unchanged
options.terrain_policy ("warn" default, or "fail"): when the terrain
elevation service is unreachable, warn substitutes 0 m MSL and reports it
truthfully (data_sources.elevation_source, elevation_fallback_points,
elevation_fallback_indices, plus one mission-level warning), while fail
returns 503 TERRAIN_UNAVAILABLE with a Retry-After header instead of a
degraded analysis. See Errors & rate limits.
POST /v1/missions/analyze (multipart/form-data)
Same analysis from a flight-plan file (.kmz, .kml, .gpx, .csv,
.wpml, .json). Send mission_file (the file) + request (a JSON string with
home, drone, battery, weather, options).
Response (both) → { "ok", "engine_version", "result": { "mission_verdict": "complete|marginal|cannot_complete", "legs": [ { "leg_index", "distance_m", "battery_start_pct", "battery_end_pct", "can_complete", "status", … } ], "total_distance_m", "final_battery_pct", "warnings": [], "path_polyline": [[lat,lon]…] }, "request_id" }.
See Errors & rate limits for the error envelope, status codes, and
rate-limit/quota headers — and /openapi.json
for every field and bound.