Skip to documentation content

Integrations

Gateway API Reference

REST endpoints and WebSocket events for local gateway integrations.

On this page

This page documents the local Gateway REST / WebSocket API — device, scene, group, energy, and system control on the gateway itself. For connecting third-party lighting, BMS, or AV/control systems, see Third-Party Lighting Integration instead.

All endpoints require a Bearer JWT in the Authorization header — see Authentication. Base URL: http://<gateway-ip>:5000/api.

WebSocket — Real-Time Events

The gateway pushes live device and health updates over a WebSocket. The published gateway reference shows this connection example. Confirm WebSocket authentication requirements for your installed release and use only an authorized local network or VPN:

const ws = new WebSocket("ws://<gateway-ip>:5000");
ws.onmessage = (e) => console.log(JSON.parse(e.data));

On connection you immediately receive a welcome event, followed by a continuous stream of state and health events.

Event types

typePayload
welcome{ type, message, time } — sent once on connect
bridge_health{ type, serialConnected, casambiPaired, casambiStatus, lastPacketAt, timestamp }
deviceState{ type, deviceId, state } — pushed whenever a light or sensor changes. The state object carries only what changed: dimmer, power, brightness, cct, color, white, motion, presence, lux, daylight

Scene, alert, and activity actions also emit events on this socket.

Example event

{
  "type": "deviceState",
  "deviceId": "ea298ea5-dd07-48a1-becb-620b6fecc669",
  "state": { "power": true, "brightness": 30, "dimmer": 254, "timestamp": 1786143137911 }
}

Devices

List devices

GET /api/devices → { success, devices[], source }

Filter the list with ?category=light or ?subtype=<subtype>.

Get a device

GET /api/devices/:id → { success, device }

The device.state object holds the live state of the fixture:

{
  "state": {
    "dimmer": 254,
    "cct": 3000,
    "white": 81,
    "color": { "hue": 0, "saturation": 255 },
    "xy": { "x": 0, "y": 0 }
  }
}

Control a device

PUT /api/devices/:id/control — control uses PUT (not POST).

{ "power": true, "brightness": 60, "colorTemp": 3000 }

RGB colour is also accepted: { "r": 255, "g": 100, "b": 0 }.

A successful command returns the confirmed state:

{
  "success": true,
  "message": "Device controlled successfully",
  "serialControl": "succeeded",
  "deviceId": "...",
  "state": { "cct": 3000, "white": 81, "color": { "hue": 0, "saturation": 255 } }
}

Commands are delivered to the fixture over the serial / Casambi link. If a device does not acknowledge, the call returns 500 with "Failed to send control command via serial". Subscribe to the WebSocket deviceState event to confirm a change actually landed on the hardware.

Sensors

  • GET /api/sensors — all sensors → { success, sensors[] }
  • GET /api/sensors/live — latest values → { success, sensors, count, timestamp, source }
  • GET /api/sensors/history/:nodeId — history for a sensor node. nodeId is the numeric node id (e.g. 5) → { success, nodeId, total, page, limit, totalPages, history[] }
  • GET /api/devices/sensors/motion — motion sensors
  • GET /api/devices/sensors/daylight — daylight/lux sensors

Lighting States

Capture and recall the exact state of a device or a whole area.

  • GET /api/light-states/device/:deviceId → { success, state }
  • GET /api/light-states/area/:areaId → { success, states[] }
  • POST /api/light-states/device/:deviceId — save the device's current state
  • POST /api/light-states/bulk — save states for multiple devices in one call

Scenes

  • GET /api/scenes → { success, scenes[] }
  • POST /api/scenes — create a scene: { "name": "Evening", "description": "..." }
  • PUT /api/scenes/:id — update
  • DELETE /api/scenes/:id
  • POST /api/scenes/:id/activate — recall the scene

Groups

Control multiple devices at once.

  • GET /api/groups → { success, groups[] }
  • POST /api/groups — create a group
  • PUT /api/groups/:id/control — same body as device control, applied to every member

Energy

  • GET /api/energy-logs — raw log entries
  • GET /api/energy-logs/stats — aggregated statistics
  • GET /api/energy-logs/carbon → { totalEmissions, bySource, totalKwh, emissionFactor }
  • GET /api/energy-logs/cost — cost breakdown → { byArea[] }
  • GET /api/energy-logs/device/:deviceId — per-device energy history

Spaces (Areas & Floors)

  • GET /api/spaces → { success, spaces[] }
  • POST /api/spaces — create a space
  • GET /api/spaces/:id/devices — devices in a space
  • GET /api/spaces/:id/stats → { success, childSpaces, deviceCount, sceneCount }
  • GET /api/floorplans

Alerts

  • GET /api/alerts · POST /api/alerts · PUT /api/alerts/:id · DELETE /api/alerts/:id

Example create body:

{ "name": "High Energy Usage", "type": "energy", "threshold": 5.0, "zone": "Lobby" }

Activities

Live system activity feed.

  • GET /api/activities — the activity feed (returns an array)
  • GET /api/activities/stats → { total, unread, byType, byArea }
  • PUT /api/activities/mark-all-read

Schedules

Time-based automation.

  • GET /api/schedule-events → { success, events[] }
  • POST /api/schedule-events · PUT /api/schedule-events/:id · DELETE /api/schedule-events/:id

System

  • GET /api/health → { overall, timestamp, version, components: { api, database, serial, firestore } }
  • GET /api/system/info → { success, data: { hostname, os, uptime, cpuTemp, memory, disk } }
  • GET /api/system/network → { success, data: { interfaces, wifi } }
  • POST /api/system/reboot — ⚠️ reboots the gateway; all control and API access drops until it restarts. Use with care.

Quick Start & Testing

# 1. List devices
curl -s http://<gateway-ip>:5000/api/devices \
  -H "Authorization: Bearer <token>"

# 2. Read one device's live state
curl -s http://<gateway-ip>:5000/api/devices/<id> \
  -H "Authorization: Bearer <token>"

# 3. Turn a light on at 60%
curl -s -X PUT http://<gateway-ip>:5000/api/devices/<id>/control \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"power": true, "brightness": 60}'

Watch the effect live:

const ws = new WebSocket("ws://<gateway-ip>:5000");
ws.onmessage = (e) => console.log(JSON.parse(e.data));
// → a "welcome" event, then "deviceState" events as lights and sensors change

Response shapes

Successful responses wrap their payload in a top-level key that varies by endpoint — for example devices, sensors, scenes, state, events, or data, and a few (such as /api/activities) return a bare array. Read the key named for the resource; most responses also include success: true.

Error Handling

CodeMeaning
200Success
400Bad request — check body or parameters
401Unauthorized — missing or expired token
403Forbidden — valid token, insufficient permission
404Not found
429Rate limit exceeded
500Server error (includes a fixture that did not acknowledge a control command)

Error format:

{ "error": "Unauthorized", "message": "Token expired", "statusCode": 401 }