API AND SDK

Build on the agent.

A REST control surface for integration, a raw MAVLink WebSocket relay for real-time flight data, MQTT topics for the cloud relay, and plugin SDKs in Python and Rust. Everything you need to build on top of the drone.
first call: agent status
curl http://<board-ip>:8080/api/status \
  -H "X-ADOS-Key: <your-key>"
239
HTTP routes on :8080
WS
MAVLink relay
JSON
Response format
API key
Auth

REST API

A full REST control surface.

The control surface binds port 8080 and serves 239 routes: 199 native Rust routes and 40 proxied to the Python feature service. Responses are JSON. A paired agent expects its key in the X-ADOS-Key header. The complete route table is generated from the router and published in the agent repo as docs/api-surface.md; the nine below are the ones an integration starts with.

GET/api/status
System health, uptime, FC connection state, agent version
GET/api/telemetry
Vehicle state: attitude, GPS, battery, RC channels, flight mode
GET/api/params
The full cached flight controller parameter list
POST/api/command
Arm, disarm, takeoff, land, RTL, mode, kill switch, pause and resume mission. Reports the FC's acknowledgement
GET/api/commands
Catalog of supported command names and what each one does
GET/api/config
Agent configuration, parsed to JSON
PUT/api/config
Update one configuration key and persist it to disk
GET/api/services
State of every managed service: running, stopped, failed
GET/api/logs
Structured log entries with service and level filters

TRANSPORTS

Ports and topics.

The agent exposes local ports for direct integration and MQTT topics for the optional cloud relay. Every transport speaks the same underlying MAVLink.

Ports and MQTT topics
REST control surface, setup webapp, WHEP video
TCP :8080
MAVLink WebSocket relay
TCP :8765
Raw MAVLink TCP proxy
TCP :5760
Raw MAVLink UDP proxies
UDP :14550, :14551
RTSP video
TCP :8554
Logging store read plane
TCP :8090
Cloud MAVLink from the drone
ados/{id}/mavlink/tx
Cloud MAVLink to the drone
ados/{id}/mavlink/rx
Cloud WebRTC signaling
ados/{id}/webrtc/offer

EXAMPLES

Quick start.

telemetry over REST
curl -s http://<board-ip>:8080/api/telemetry \
  -H "X-ADOS-Key: <your-key>" | jq

{
  "armed": true,
  "mode": "GUIDED",
  "battery": { "voltage": 22.4, "current": 12.1, "remaining": 78 },
  "gps": { "fix_type": 3, "satellites": 14 },
  "position": { "lat": 47.3977, "lon": 8.5456, "alt_rel": 50.2 },
  "attitude": { "roll": 0.02, "pitch": -0.01, "yaw": 3.18 }
}
python client
import httpx

BASE = "http://<board-ip>:8080"
headers = {"X-ADOS-Key": "<your-key>"}

telem = httpx.get(f"{BASE}/api/telemetry", headers=headers).json()
print(telem["battery"]["remaining"], telem["gps"]["satellites"])

httpx.post(
    f"{BASE}/api/command",
    headers=headers,
    json={"cmd": "takeoff", "args": [10]},
)

WEBSOCKET

Raw MAVLink relay.

The relay on port 8765 forwards raw MAVLink v2 between the flight controller and any number of consumers. Wire-compatible with the ArduPilot SITL WebSocket bridge.

  • ✓Bidirectional: read telemetry and send commands
  • ✓Raw binary MAVLink v2 frames, no JSON wrapping
  • ✓Multi-consumer: many clients connect at once
  • ✓Wire-compatible with the ArduPilot SITL bridge
  • ✓Frames are forwarded, not re-encoded or buffered into batches
browser websocket
const ws = new WebSocket("ws://<board-ip>:8765");
ws.binaryType = "arraybuffer";

// inbound: raw MAVLink v2 frames from the flight controller
ws.onmessage = (e) => decodeMavlink(new Uint8Array(e.data));

// outbound: send a frame straight to the FC
ws.send(encodeCommandLong(sysid, compid, cmd, params));
Multi-consumer routing
Flight controllerUART or USB
MAVLink routerone in, many out
WebSocket:8765
web GCS
TCP:5760
direct GCS
UDP:14550, :14551
direct GCS
One MAVLink stream, three transport endpoints, many consumers at once.

PLUGIN SDKS

ados.sdk and ados-sdk

Plugin and driver authors get the same surface in two languages: the Python ados.sdk and the Rust ados-sdk crate. Both ship with the agent and expose the same stable base classes for hardware drivers, the on-vehicle vision bus, and a plugin test harness.

CameraDriver

Camera drivers over CSI, USB UVC, IP, and vendor SDKs

GimbalDriver

Gimbal drivers with pan, tilt, and roll control

LidarDriver

LiDAR and rangefinder drivers

GpsDriver

GPS and GNSS receiver drivers

EscDriver

ESC drivers with telemetry feedback

VisionClient

Read frames and detections from the on-vehicle vision bus

PayloadActuatorDriver

Drivers for releases, winches, and other payload actuators

SECURITY

Pairing key, then scoped tokens.

A paired agent requires its pairing key in the X-ADOS-Key header, and that key carries full access. An unpaired agent answers on the LAN with no key at all, so pairing is the first thing you do. For AI and automation clients the agent also accepts a scoped, revocable token on x-ados-mcp-token, admitted per route against the scope groups below. That lane is fail-closed and off until you turn it on: a write with no declared scope class is unreachable by token.

readEvery GET except plugin lifecycle: telemetry, status, params, services, logs. No state changes.
secret_readA read whose body would carry a secret. Separate, so a read token cannot reach one.
safe_writeReversible operator writes: vision target designation and log push.
flightAnything that can move the aircraft: POST /api/command, CAN passthrough, RC channel injection, taking pilot-in-command.
adminParameter writes, service restarts, radio and network changes, model upload, plugin config.
destructiveUnpairing, which tears down the trust relationship with the ground station.

Read the full API reference.

Complete endpoints, the WebSocket protocol, and the SDK documentation on GitHub.

View on GitHub
Get Early Access