How command delivery works
XpectraFlow never talks to your vehicle. It hands the command to your system, and you own the last mile.
Start with what we do not do
XpectraFlow does not transmit to your vehicle. Not over MAVLink, not over a radio, not at all. The ingest path binds sockets it never writes to; there is no command message on any telemetry subject, and a test asserts it stays that way.
That is a deliberate boundary, not an unfinished feature. The moment a system can command a vehicle it inherits a regulatory surface, and we would rather not stand between your operator and your aircraft.
So when an operator issues a command in the Command Center, this is what happens: we POST a signed notification to an HTTPS endpoint you registered, and your system decides what to do with it. You own the last mile. You keep the interlocks, the radio, and the responsibility.
If you do not register a webhook endpoint, the Command Center is a log. Commands are recorded, annotated on the chart, and never sent anywhere. That is a perfectly reasonable way to use it, and it is the default.
The sequence
sequenceDiagram
participant Op as Operator (console)
participant XF as XpectraFlow
participant Q as Command queue
participant You as Your receiver
participant V as Your vehicle
Op->>XF: log a command
Note over XF: status: logged<br/>nothing is sent
Op->>XF: POST /api/commands/dispatch
XF->>XF: kill switch? armed? endpoint?
XF->>Q: queue it
Note over XF: status: queued
Q->>You: POST, HMAC-signed
You-->>Q: 200
Note over XF: status: delivered
You->>V: your uplink, your rules
V-->>You: accepted
You->>XF: POST /api/commands/ack
Note over XF: status: ackedNote where the vehicle appears: only on your side of the diagram.
The states
| State | Means |
|---|---|
logged | Recorded. Nothing has been sent. |
queued | Dispatched, waiting to go out |
delivered | Your endpoint returned 2xx |
acked | Your system reported the vehicle took it |
nacked | Your system reported it was rejected |
timed_out | Delivered, and then silence past the deadline |
failed | Five delivery attempts, or your endpoint refused it |
retracted | An operator withdrew it |
delivered does not mean the vehicle heard anything. It means your server
returned a 2xx. The word is not transmitted, deliberately — in eighteen months
somebody reading this database should not be able to conclude that we transmit.
acked is the state that means something reached a vehicle, and it is a state
only you can put a command into.
timed_out is the one worth watching. It means we handed the command over and
heard nothing back, so nobody knows whether the vehicle acted. That ambiguity is
exactly what an operator needs to see rather than have smoothed over.
What you have to build
Register an endpoint
POST /api/webhooks/create gives you a signing secret, once. See
the webhooks reference.
Build a receiver
Verify the signature, respond 2xx quickly, and do the uplink asynchronously. The receiver guide has working code in Python and Node.
Arm the dataset
Nothing is delivered for a dataset that is not armed, and arming expires. See Arming.
Acknowledge
Tell us what the vehicle did, using the one-time token in the payload. Without
this every command ends at timed_out.