Skip to content

MQTT API

Broker & connection

CoppelBox devices connect to AWS IoT Core as the MQTT broker.

PropertyValue
ProtocolMQTT over TLS 1.2
Port8883
AuthenticationMutual TLS — X.509 client certificate, no username/password
Topic access controlEnforced by AWS IoT policy, scoped per-device to that device's own topics

There is no username/password mode and no anonymous access. A device (or any other client) authenticates purely by presenting a valid, IoT-Core-registered X.509 certificate during the TLS handshake — see Authentication & Access for how that certificate model works and what it means for third-party integrators.

Topic structure (/cbox/...)

All CoppelBox MQTT traffic uses a hierarchical topic with a leading slash:

/cbox/{DEVICE_ID}/{subtopic}
  • {DEVICE_ID} — the device's unique identifier, derived from its MAC address (e.g. CBOX-F8B3B737B800)
  • {subtopic} — the message category (status, alerts, command, etc.)

The leading slash matters

/cbox/... is correct — not cbox/.... This is a known gotcha: dropping the leading slash is the most common cause of a subscription silently receiving nothing.

Topics a device publishes to (i.e. what you subscribe to, to receive data):

TopicPurposeFrequency
/cbox/{DEVICE_ID}/statusSystem status, health, and relay state changes (includes energy data)Every 20 seconds + on relay change
/cbox/{DEVICE_ID}/alertsFault and warning eventsOn alert / clear / resend
/cbox/{DEVICE_ID}/powerBuffered power history samplesOn buffer flush
/cbox/{DEVICE_ID}/ivyIvy Board telemetry (if fitted)Every 60 seconds
/cbox/{DEVICE_ID}/configRelay configuration (type: "relayConfig")On MQTT connect + after a config change
/cbox/{DEVICE_ID}/otaOTA firmware update progress and post-update notificationsDuring/after an update
/cbox/{DEVICE_ID}/commandCommand responses and acknowledgmentsOn request

Topics a device subscribes to (i.e. where you'd publish, to send it a command):

TopicPurpose
/cbox/{DEVICE_ID}/commandControl commands (relay control, status requests, diagnostics, etc.)

Certificate rotation (/cbox/{DEVICE_ID}/csr/...) is a device-internal cloud handshake and not relevant to a data-consumption integration — it's mentioned here only so you don't mistake it for a telemetry topic if you subscribe with a wildcard (/cbox/{DEVICE_ID}/#).

Message payloads

Every telemetry and response message carries three timestamp fields:

FieldTypeDescription
timestringISO 8601 UTC timestamp with milliseconds
timeUnumberUnix epoch seconds
uptimenumberSeconds since device boot

The core payload types are:

  • Status packet (heartbeat) — the main telemetry message, published every 20 seconds. See Telemetry → Status packets for the full field breakdown.
  • Relay delta — a lightweight message published immediately on a relay state change (type: "rlyDelta").
  • Relay config — the full per-relay configuration, published on connect and after any config change (type: "relayConfig").
  • Power history — buffered energy-meter samples. See Telemetry → Power data.
  • Alerts — fault/warning events. See Alerts for the full spec.

Field names on the wire are deliberately compact (e.g. batt not battery, PkW not power_kW) — this keeps status packets under 1 KB. See Examples for complete sample payloads of each message type.

Commands

Commands are sent as JSON to /cbox/{DEVICE_ID}/command. All commands are validated before execution; an invalid or missing parameter produces an error response on the same topic rather than being silently dropped.

The commands most relevant to a data-integration (rather than a fleet-control) use case are:

CommandPurposeResponse topic
request_status_packetRequest an immediate, complete status packet (rather than waiting up to 20s for the next heartbeat)/status
get_relay_configRequest the current relay configuration (labels, modes, pulse durations)/command

Example — request an immediate status packet:

json
{
  "command": "request_status_packet"
}

Relay-control commands (relay, toggle_relay, pulse_relay) and the rest of the command surface exist, but actuating a device is normally done through the platform's GraphQL API (publishDeviceCommand) rather than by publishing MQTT directly — see Authentication & Access. See Examples for a worked command/response pair.