nexalwarenexalwaredocs
API Reference

WebSocket

A live push feed for device state changes, commands, and schedule activity.

GET /api/v1/ws streams device events to your application in real time, so you don't have to poll for changes.

Requires a session token

Authenticate with the token query parameter set to a session token from Log in - not an API key. There's no API-key-authenticated version of this feed yet. If your integration only holds an API key, poll GET /devices/{deviceId}/telemetry/latest instead - see Subscribe to Device Events for both approaches side by side.

Connect

const ws = new WebSocket(
  `wss://api.nexalware.com/api/v1/ws?token=${sessionAccessToken}`,
);

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  // msg.type identifies which kind of message this is - see below.
};

If the token is missing, invalid, or expired, the connection closes immediately with code 4001. Treat that as a signal to obtain a fresh token and reconnect, not as a transient network error.

Messages

Every message is a JSON object with a type field. An initial_state message arrives immediately on connect; everything after that is pushed as it happens, in real time, for as long as the connection stays open.

initial_state

Sent once, immediately after connecting: a snapshot of every device on your account, so your UI has something to render before any live event arrives.

{
  "type": "initial_state",
  "devices": [
    {
      "deviceId": "dev_a1b2c3",
      "name": "Greenhouse Pump",
      "relay": true,
      "isOnline": true,
      "lastSeen": 1732000000
    }
  ]
}

device_online / device_offline

Sent when a device's connection status changes - either because the device itself connected or disconnected, or because Nexalware detected it had gone quiet.

{ "type": "device_online", "deviceId": "dev_a1b2c3", "accountId": "acc_x1y2z3", "timestamp": 1732000000000 }
{ "type": "device_offline", "deviceId": "dev_a1b2c3", "accountId": "acc_x1y2z3", "timestamp": 1732000000000 }

relay_changed

Sent when a device reports that its relay changed state. This reflects what the device itself reported back, not a direct echo of a command you sent.

{
  "type": "relay_changed",
  "deviceId": "dev_a1b2c3",
  "accountId": "acc_x1y2z3",
  "relay": true,
  "triggeredBy": "device",
  "timestamp": 1732000000000
}

telemetry

Sent once per reported metric - a device reporting three readings at once produces three separate messages, not one batched message.

{
  "type": "telemetry",
  "deviceId": "dev_a1b2c3",
  "accountId": "acc_x1y2z3",
  "metric": "temperature",
  "value": 21.4,
  "valueText": null,
  "unit": "celsius",
  "timestamp": 1732000000000
}

schedule_fired

Sent when a schedule reaches its on or off time and dispatches its command.

{
  "type": "schedule_fired",
  "accountId": "acc_x1y2z3",
  "deviceId": "dev_a1b2c3",
  "slot": 0,
  "command": "ON",
  "timestamp": 1732000000000
}

More event types may be added over time

Handle unrecognized msg.type values by ignoring them rather than treating them as errors, so your integration keeps working as new event types are introduced.

On this page