Skip to content

API reference ​

Before you start ​

This page is the reference for the Payloads API that a payload or an operator calls in MC. A payload on the device API path does not call it: the bus does.

For the self-announce path, obtain the connection details from Urban Sky. This reference covers Payloads API version 1.

Device API (port 8090) ​

Served by your payload, read by the bus on the payload LAN. Guide and examples: Serve the device API.

Method and pathPurpose
GET /api/v1/capabilitiesschema_version: "urbansky.payload_api.v1", modules, identity, telemetry_fields, commands, and optional streams, services, metrics.
GET /api/v1/telemetryschema_version, hostname, generated_at, values.
POST /api/v1/command{command, parameters, request_id}. Answers 200, 400, 409 in_progress or 503.

The bus forwards a command only when its module is in modules, is not reserved (gimbal, rotor, gps, camera, jetson, bus, api), and is named in the bus's PAYLOAD_LAN_MODULES.

Endpoint summary ​

serial identifies the device; :id is its registration UUID. Device requests use x-device-api-token; operator requests use a signed-in operator’s access JWT for the same organization. SDK/API tokens do not grant access to these operator endpoints.

Method and pathCallerPurpose
POST /payloads/announceDeviceRegister or refresh identity, reachability, and inline manifests.
POST /payloads/heartbeatDeviceRefresh the address and liveness.
POST /payloads/telemetryDeviceSubmit a JSON or protobuf telemetry batch.
GET /payloadsOperator, payload readList the organization's registrations.
GET /payloads/:idOperator, payload readInspect a registration.
GET /payloads/:id/telemetryOperator, payload readRead up to 50 samples from the last seven days, newest sample time first. limit up to 500.
GET /payloads/:id/ingest-rejectionsOperator, payload readRead telemetry rejections from the last seven days. Optional limit and since.
GET /payloads/:id/command-auditOperator, payload readRead sent commands, newest first. limit 1–200, requestId, and cursor from X-Next-Cursor.
POST /payloadsOperator, payload writeCreate an operator-authored registration, adopted immediately.
PUT /payloads/:idOperator, payload writeChange settings, manifest sources, or command enablement.
POST /payloads/:id/adoptOperator, payload writeAdopt a discovered device.
POST /payloads/:id/restoreOperator, payload writeReturn a retired registration to discovered, with commands disabled.
POST /payloads/:id/commandsOperator, payload writeValidate and dispatch a declared command; registry commands can need higher roles.
GET /payloads/:id/video-streamsOperator, payload readObtain playback metadata when video is configured.
POST /payloads/:id/sharesOperator, payload writeMint a time-limited SRT address for the camera stream. The address is shown once. See Share the stream.
GET /payloads/:id/sharesOperator, payload writeList live shares of the camera stream, without credentials.
DELETE /payloads/:id/shares/:userOperator, payload writeRevoke one share now.
DELETE /payloads/:idOperator, payload writeRetire a registration. MC keeps its history. Device traffic cannot restore it.
POST /commands on the deviceMC, using mTLS in this guideDeliver the command to your hardware adapter.

Payload read means mission-control:payload:read; payload write means mission-control:payload:write.

On a Husky bus, the payload also sends logs and metrics to the bus itself, not to MC. These routes are on the bus's payload-LAN address, port 4318, with no credentials:

Method and pathCallerPurpose
POST /api/v1/payload/logsDeviceLog lines as JSON lines.
POST /api/v1/payload/metricsDeviceDeclared gauge and counter values as JSON.
POST /v1/logs, /v1/metricsDeviceThe same as OTLP/HTTP, for an OpenTelemetry SDK.
GET /api/v1/payload/statusDeviceWhat the bus received from your payload, and what it dropped.

PayloadTelemetry in the Python and JavaScript SDKs uses these routes. Limits and rules: Run on a Husky bus.

Message shapes ​

MessageMain fieldsExample
AnnouncementschemaVersion, identity, reachability, codec, security, manifests, optional streams and servicesFirst announcement
Telemetry manifestschemaVersion, fields, staleAfterS, optional minMessageIntervalMsTelemetry fields
Telemetry batchserial, schemaVersion, samples containing timestamp, seq, valuesSend a measurement
Heartbeatserial, address, optional timestampSend a heartbeat
Command manifestschemaVersion, commands containing name, description, confirm, paramsDefine a command
Operator commandname, params, optional relay via or retry requestIdSend a command
Device commandname, requestId, params, optional targetSerialImplement the handler
Device acknowledgmentMatching requestId, state, optional reason and resultAcknowledgment states
Operator command resultrequestId, nested ack, optional deduplicated and contention advisoryVerify the result

Announcements and heartbeats use JSON. Telemetry accepts JSON or raw protobuf with application/x-protobuf. MC sends device commands as JSON regardless of the telemetry codec.

Complete announcement ​

ENV-001 with telemetry and command support
json
{
  "schemaVersion": 1,
  "identity": {
    "serial": "ENV-001",
    "name": "Environmental sensor",
    "vendor": "Example Instruments"
  },
  "reachability": {
    "address": "100.64.0.42",
    "port": 8091,
    "protocol": "https",
    "networkMode": "NETWORK_MODE_SHARED_VPN"
  },
  "codec": "CODEC_JSON",
  "security": "SECURITY_TRANSPORT_MTLS",
  "telemetryManifest": {
    "schemaVersion": 1,
    "staleAfterS": 30,
    "fields": [
      {
        "key": "sensor.temperature_c",
        "label": "Temperature",
        "type": "FIELD_TYPE_NUMBER",
        "unit": "°C",
        "min": -80,
        "max": 125
      },
      {
        "key": "sensor.sample_period_s",
        "label": "Applied sample period",
        "type": "FIELD_TYPE_NUMBER",
        "unit": "s",
        "min": 1,
        "max": 60
      },
      {
        "key": "sensor.state",
        "label": "Sensor state",
        "type": "FIELD_TYPE_ENUM",
        "values": ["idle", "sampling", "fault"]
      }
    ]
  },
  "commandManifest": {
    "schemaVersion": 1,
    "commands": [
      {
        "name": "sensor.set_sample_period",
        "description": "Set the measurement interval in seconds. Read back the applied interval in telemetry.",
        "confirm": true,
        "params": [
          {
            "key": "seconds",
            "label": "Sample period",
            "type": "FIELD_TYPE_NUMBER",
            "unit": "s",
            "min": 1,
            "max": 60,
            "required": true
          }
        ]
      }
    ]
  }
}

Manifest rules ​

  • Use camelCase property names and full enum strings.
  • Types: FIELD_TYPE_NUMBER, FIELD_TYPE_STRING, FIELD_TYPE_BOOLEAN, FIELD_TYPE_ENUM. Enums require values.
  • Keep telemetry keys and command names unique; parameter keys must be unique within a command.
  • Declare at least one field or command. Either list may otherwise be empty. On re-announcement, omitting a manifest preserves it; send an empty fields or commands list to remove that capability set. The same announcement must still include a nonempty list for the other manifest, because the check counts only entries in the current request and a stored manifest does not satisfy it.
  • Match hardware units and bounds. Only required: false makes a parameter optional; enforce integer-only rules in the device.
  • confirm requests UI confirmation; it is not authorization or an interlock.
  • Set audience: "AUDIENCE_ENGINEERING" on a command or telemetry field for tuning, diagnostics, and bench use. MC does not show it to operators. Omit audience for everything that operators use. Engineering is not a safety lock: leave a command out of the manifest until it is safe to send remotely.
  • Set sensitive: true on a parameter whose value MC must not store in a mission plan. The operator supplies the value when the command is sent.
  • staleAfterS must exceed normal reporting delay. Optional minMessageIntervalMs controls persistence thinning, not sampling.
  • Generate manifests and validation from one registry. Omit unavailable measurements rather than invent values.

Limits and timing ​

ItemLimit or behavior
Payload serialUp to 64 letters, digits, _, ., :, or -.
Each manifest64 KiB.
Telemetry fields200 per manifest.
Commands100 per manifest.
Samples100 per batch.
Values300 per sample.
String value1,024 characters.
Sequence numberExact integer range 0 through 9007199254740991.
Future sample timestampMore than five minutes ahead of MC is rejected.
Direct command request10-second timeout.
Manifest fetchFive-second timeout and 64 KiB cap; cached for five minutes.
Example loop intervalsReporting every 2 seconds, heartbeat and capability refresh every 15 seconds; implementation defaults, not protocol requirements.

Network modes ​

ModeRouting
NETWORK_MODE_SHARED_VPNBehind a bus. With identity.parentSerial set to the bus, MC sends commands through the bus link to your payload-LAN lease. The name is older than the bus link.
NETWORK_MODE_SHARED_LANDirect connection; MC needs a route to the LAN.
NETWORK_MODE_STATIC_IPDirect connection to the announced address.
NETWORK_MODE_PAYLOAD_VPNReserved; command routing is unavailable.

Protobuf ​

Obtain the matching .proto bundle from Urban Sky, generate a client, and encode TelemetryBatch. Send raw bytes as application/x-protobuf. Announcements, heartbeats, and device commands remain JSON.

Optional integrations ​

Serve manifests by URL ​

Set telemetrySchemaUrl or commandsUrl through PUT /payloads/:id. The URL must match the registered host and protocol. A nonempty URL clears its stored inline manifest; re-announcing an inline manifest makes that source take precedence again.

Serve a contract TelemetryManifest or CommandManifest. MC applies the same limits, with a five-second fetch timeout and five-minute cache. An unreachable telemetry schema fails ingestion with 503.

Gateway children and relays ​

Announce each child with its own serial, identity.parentSerial, and the gateway's address/port. Set reachability.dispatch: "parent" to send the child's commands through its gateway. A gateway that MC cannot reach directly announces no address. One enrolled credential may own multiple serials. Adopt and enable each child separately; route commands by targetSerial and reject unknown targets.

reachability.relays declares alternate routes; stratcom is the supported last leg. Operators select a relay with via. Direct failures never silently fall back, and relay acceptance does not confirm delivery.

For positional RF commands, preserve manifest parameter order, omit only trailing optional arguments, and reject argument values containing whitespace.

Video ​

Do not send video bytes as telemetry. Declare each video source in streams:

json
"streams": [{ "name": "eo", "protocol": "srt", "port": 9595 }]
FieldRule
protocolMust be srt (any letter case). MC ignores other declarations.
urlOptional srt:// or srts:// URL, 2,048 characters maximum. Use it when the video is served from another host.
portUsed when url is empty. MC pulls from srt://<reachability.address>:<port>. Default 9595.
nameYour label for the stream.

MC plays one camera source for each payload. It uses the first SRT declaration with a url. If no SRT declaration has a url, MC uses the first SRT declaration with the announced address. Use 8 streams or fewer, 8 KiB of JSON or less in total.

Send MPEG-TS over SRT. H.264 and H.265 are accepted. MC transcodes the video to H.264 for browsers. Confirm the codec, resolution, and network route with Urban Sky before flight.

Camera metadata (KLV) ​

If the camera knows where it points, put MISB ST 0601 KLV metadata in the MPEG-TS stream. MC keeps the KLV track on the raw stream. MC can use the following tags:

TagsContent
1Checksum. Required: MC ignores a packet with a bad checksum.
2UTC time, microseconds. Match it to the frame time.
5–7Platform heading, pitch, and roll.
13–15Sensor latitude, longitude, and altitude (MSL).
16–17Horizontal and vertical field of view.
18–20Sensor azimuth, elevation, and roll, relative to the platform.
21Slant range.
23–25Frame center.
26–33, 82–89Frame corners (offset or full).

MC adds tag 5 and tag 18 to get the camera compass bearing. Elevation is negative below the horizon. MC marks a footprint as suspect when its computed slant range differs from tag 21 by more than 20%. GET /payloads/:id/camera-pose returns the poses of the last 30 seconds. Confirm with Urban Sky that KLV overlays are enabled for your payload.

Share the stream ​

POST /payloads/:id/shares returns an SRT read address that expires. MC shows the address one time only.

FieldRule
kindpicture (default): the transcoded stream. raw: the camera stream with KLV. raw is not available to operators.
ttlSecondsDefault 3600. MC limits it to 60–28800.

Public sharing can be off in an environment. Ask Urban Sky.

Pointing conventions ​

Use these names if your payload points a camera. MC's existing camera and gimbal controls read them:

NameMeaning
gimbal.az_deg, gimbal.el_degActual camera azimuth as a compass heading, and elevation.
gimbal.target_az_deg, gimbal.target_el_degThe target the device holds.
gimbal.connectedWhether the gimbal is up.
gimbal.set_az, gimbal.set_el, gimbal.set_azelCommands with az_deg and el_deg parameters.

MC shows an axis as arrived when it is within 1° of its target. The test for arrival works across 0°/360°. Other names work, but they appear as generic fields and commands.

Display hints ​

All display hints are optional. They change only how MC shows a value or command. Permissions, validation, and confirmation never depend on them.

WhereFields
Either manifestgroups: id, label, description, kind (DISPLAY_GROUP_KIND_PRIMARY, _STATUS, _SETTINGS, _ADVANCED, _DIAGNOSTICS, _DANGER), collapsedByDefault. Up to 32.
Telemetry fielddescription, valueLabels (for enum values or "true"/"false"), warnAbove, critAbove, warnBelow, critBelow, per-field staleAfterS.
Field presentationgroupId, precision (0–12), normalMin, normalMax, primary, trend, format (VALUE_FORMAT_DURATION, VALUE_FORMAT_BYTES), connectedOf.
Command presentationlabel, groupId, style (COMMAND_DISPLAY_STYLE_ACTION, _INLINE, _FORM), settleMs, risk (COMMAND_RISK_SAFE, _CAUTION, _DANGER), confirmTitle, consequences (up to 4), endsModes.
Parameter presentationwidget (INPUT_WIDGET_TOGGLE, _SLIDER, _NUMBER, _SELECT, _SEGMENTED, _TEXT), scale (VALUE_SCALE_LINEAR, VALUE_SCALE_LOG10), step, readbackKey.
  • normalMin and normalMax mark the healthy range inside min/max. Warnings still come from the warn* and crit* thresholds.
  • connectedOf goes on a boolean field. false means that the named part is down.
  • readbackKey names the telemetry field that reports the applied value. MC shows that reading as the actual state.
  • risk changes the display only. Without it, confirm: true shows as caution.
  • VALUE_SCALE_LOG10 requires a positive min.

Ask Urban Sky before you depend on a custom widget or a semanticRole.


← Troubleshooting · Next: Run on a Husky bus →