Skip to content

Alerts

How alerts are generated

Alerts originate on the device itself — firmware detects a fault or security-relevant condition (AC power loss, a power meter going offline, the local web-config AP being activated, and similar) and publishes an alert message. From there:

Device
  │  Detects fault/warning condition
  │  MQTT publish to /cbox/{deviceId}/alerts

AWS IoT Core
  │  IoT Rule (writes directly to DynamoDB — no Lambda in this path)

DynamoDB
  │  DynamoDB Stream

Lambda (DynamoDB-to-AppSync)
  │  GraphQL mutation

AppSync  ──  WebSocket  ──▶  Your application (real-time alert display)

An alert also sets hasAlerts: true in the device's regular status packet, and active alerts (state alert or warning) are summarised inline in an alerts object within the heartbeat — so a client watching only the status stream still knows something is wrong, even before/without consuming the alerts topic directly.

Alert payload structure

Fault alert example (AC power loss, critical):

json
{
  "deviceId": "CBOX-00001",
  "time": "2024-01-15T14:30:45.123Z",
  "timeU": 1705329045,
  "uptime": 782,
  "alert_timestamp": 782,
  "alert_id": "AC_POWER_LOSS",
  "instance_id": "AC_POWER_LOSS_782",
  "priority": "critical",
  "state": "alert",
  "message": "Lost AC Power Input",
  "details": {
    "voltage": 45.2,
    "meter_type": "internal",
    "threshold_low": 50,
    "threshold_high": 60
  },
  "resend_count": 0
}

Warning alert example (AP activated — security-relevant, not a fault):

json
{
  "deviceId": "CBOX-00001",
  "time": "2026-02-24T10:30:00.000Z",
  "timeU": 1771933800,
  "uptime": 355,
  "alert_timestamp": 355,
  "alert_id": "AP_ACTIVATED",
  "instance_id": "AP_ACTIVATED_355",
  "priority": "medium",
  "state": "warning",
  "message": "AP web server activated",
  "details": { "client_count": 0 },
  "resend_count": 0
}

Fields

FieldDescription
alert_idAlert type identifier — see table below
instance_idUnique ID for this specific occurrence, format {ALERT_ID}_{device_uptime}
prioritycritical | high | medium | low
stateAlert lifecycle state — see below
messageHuman-readable description
detailsAlert-type-specific data (varies by alert_id)
resend_countIncrements each time an unacknowledged alert is resent

Alert types

alert_idPriorityTrigger
AC_POWER_LOSScriticalAC voltage drops below 50V (clears above 60V)
DC_POWER_LOSScritical12VDC input fault
EXTERNAL_METER_LOSShighExternal power meter communication lost
AP_ACTIVATEDmediumLocal web-config AP activated (security-relevant, not a fault)
CERT_AUTH_FAILUREhighDevice re-provisioned after sustained certificate authentication failure (cloud-raised, not device-raised)

Alert states

StateMeaning
alertActive fault condition
warningActive, non-fault, security/informational condition
alert_clearedThe fault or warning condition has resolved
inactiveDormant / no longer relevant

Resend behaviour

Unacknowledged alerts are resent automatically until acknowledged:

PriorityResend interval
criticalEvery 60 seconds
high / medium / lowEvery 300 seconds

Consuming alerts

If you're integrating through the platform's GraphQL API (the supported path for most integrations — see Authentication & Access), subscribe to alert updates rather than the raw MQTT topic:

graphql
subscription OnOrganizationAlerts($organizationId: String!) {
  onOrganizationAlerts(organizationId: $organizationId) {
    deviceId
    organizationId
    instance_id
    code
    priority        # CRITICAL | HIGH | MEDIUM | LOW
    state           # FAULTING | FAULT_CLEARED | DELETED
    message
    timestamp
    faultedAt
    clearedAt
    acknowledgedAt
  }
}

Use onOrganizationAlerts to receive every alert across all devices you have visibility of; use onAlertUpdate(deviceId: ...) to scope to a single device. Note that the API surfaces uppercase enum values (FAULTING, FAULT_CLEARED, CRITICAL, HIGH, …) and the field name code, where the raw MQTT/DynamoDB representation documented above uses lowercase strings (alert, alert_cleared, critical) and the field name alert_id. Use the API's field names and enum values when consuming through the API — do not assume the two representations are interchangeable.

If you're subscribing to raw MQTT (device-protocol integrations only — see Authentication & Access), subscribe to /cbox/{DEVICE_ID}/alerts and consume the payloads exactly as documented above.

Acknowledging an alert stops the automatic resend. This is sent as a device command (acknowledge_alert with the alert's instance_id) — via publishDeviceCommand if you're on the API, or directly to /cbox/{DEVICE_ID}/command if you have MQTT access.