WebSocket API
The ThingsBoard WebSocket API provides real-time, bidirectional communication between client applications and the platform. Use it to subscribe to telemetry updates, entity data changes, alarm events, and notifications — all pushed instantly without polling.
Connection
Section titled “Connection”Connect to the WebSocket endpoint:
http://localhost:8080/api/wsReplace http:// with ws:// or https:// with wss:// depending on your deployment. For self-hosted installations, use the host and port configured for your ThingsBoard instance.
Authentication
Section titled “Authentication”After opening the connection, send an authCmd with a JWT token:
{ "authCmd": { "cmdId": 0, "token": "YOUR_JWT_TOKEN" }}Obtain the JWT token from the REST API login endpoint.
The connection times out after 90 seconds of inactivity. The client should send periodic pings or commands to keep it alive.
Message format
Section titled “Message format”Requests
Section titled “Requests”All commands are sent as JSON. You can batch multiple commands in a single message:
{ "authCmd": { "cmdId": 0, "token": "JWT_TOKEN" }, "cmds": [ { "cmdId": 1, "type": "ENTITY_DATA", ... }, { "cmdId": 2, "type": "ALARM_COUNT", ... } ]}Each command has a unique cmdId (integer) chosen by the client. Responses reference this ID.
Responses
Section titled “Responses”{ "cmdId": 1, "errorCode": 0, "errorMsg": null, "cmdUpdateType": "ENTITY_DATA", ...}Error codes
Section titled “Error codes”| Code | Name | Description |
|---|---|---|
| 0 | NO_ERROR | Success |
| 1 | INTERNAL_ERROR | Internal server error |
| 2 | BAD_REQUEST | Invalid command or parameters |
| 3 | UNAUTHORIZED | Missing or invalid authentication |
Command types
Section titled “Command types”Entity data subscription
Section titled “Entity data subscription”Subscribe to entity data with filtering, pagination, and real-time updates. See the Entity Data Query API reference for the full list of entity filters, key filters, and query options.
{ "cmds": [ { "cmdId": 1, "type": "ENTITY_DATA", "query": { "entityFilter": { "type": "entityType", "entityType": "DEVICE" }, "pageLink": { "pageSize": 10, "page": 0, "sortOrder": { "key": { "type": "ENTITY_FIELD", "key": "createdTime" }, "direction": "DESC" } }, "entityFields": [ { "type": "ENTITY_FIELD", "key": "name" }, { "type": "ENTITY_FIELD", "key": "type" } ], "latestValues": [ { "type": "ATTRIBUTE", "key": "active" } ], "keyFilters": [] }, "latestCmd": { "keys": [ { "type": "TIME_SERIES", "key": "temperature" } ] } } ]}Initial response contains the full result set in data. Subsequent real-time updates arrive in the update field:
{ "cmdId": 1, "errorCode": 0, "cmdUpdateType": "ENTITY_DATA", "data": { "data": [ { "entityId": { "entityType": "DEVICE", "id": "device-uuid" }, "latest": { "ATTRIBUTE": { "active": { "ts": 1704067200000, "value": "true" } }, "TIME_SERIES": { "temperature": { "ts": 1704067260000, "value": "42.5" } } } } ], "totalPages": 1, "totalElements": 1, "hasNext": false }}Time series history — add historyCmd or tsCmd to fetch historical data or subscribe to a rolling time window:
{ "cmds": [ { "cmdId": 2, "type": "ENTITY_DATA", "query": { ... }, "tsCmd": { "keys": ["temperature", "humidity"], "startTs": 1704067200000, "timeWindow": 3600000 } } ]}Entity count
Section titled “Entity count”Get a live count of entities matching a filter:
{ "cmds": [ { "cmdId": 3, "type": "ENTITY_COUNT", "query": { "entityFilter": { "type": "entityType", "entityType": "DEVICE" }, "keyFilters": [] } } ]}Response:
{ "cmdId": 3, "errorCode": 0, "cmdUpdateType": "COUNT_DATA", "count": 42}Alarm data subscription
Section titled “Alarm data subscription”Subscribe to alarms with filtering and real-time updates. See the Alarm Query API reference for alarm-specific filters, severity and status values, and query options.
{ "cmds": [ { "cmdId": 4, "type": "ALARM_DATA", "query": { "entityFilter": { "type": "entityType", "entityType": "DEVICE" }, "pageLink": { "pageSize": 10, "page": 0, "sortOrder": { "key": { "type": "ALARM_FIELD", "key": "createdTime" }, "direction": "DESC" } }, "alarmFields": [ { "type": "ALARM_FIELD", "key": "createdTime" }, { "type": "ALARM_FIELD", "key": "type" }, { "type": "ALARM_FIELD", "key": "severity" }, { "type": "ALARM_FIELD", "key": "status" } ], "keyFilters": [] } } ]}Alarm count
Section titled “Alarm count”{ "cmds": [ { "cmdId": 5, "type": "ALARM_COUNT", "query": { "entityFilter": { "type": "entityType", "entityType": "DEVICE" }, "keyFilters": [] } } ]}Response:
{ "cmdId": 5, "errorCode": 0, "cmdUpdateType": "ALARM_COUNT_DATA", "count": 15}Alarm status
Section titled “Alarm status”Monitor whether any active alarms match the given criteria for a specific entity:
{ "cmds": [ { "cmdId": 6, "type": "ALARM_STATUS", "originatorId": { "entityType": "DEVICE", "id": "device-uuid" }, "typeList": ["HIGH_TEMPERATURE"], "severityList": ["CRITICAL", "MAJOR"] } ]}Response:
{ "cmdId": 6, "errorCode": 0, "cmdUpdateType": "ALARM_STATUS", "active": true}Pass null for typeList or severityList to match all alarm types or severities.
Notifications
Section titled “Notifications”Subscribe to user notifications:
{ "cmds": [ { "cmdId": 7, "type": "NOTIFICATIONS", "limit": 10 } ]}Response:
{ "cmdId": 7, "errorCode": 0, "cmdUpdateType": "NOTIFICATIONS", "totalUnreadCount": 5, "notifications": [ { "id": "notification-uuid", "createdTime": 1704067200000, "type": "ALARM", "text": "High temperature detected", "read": false } ]}Get unread count only:
{ "cmds": [{ "cmdId": 8, "type": "NOTIFICATIONS_COUNT" }] }Mark as read:
{ "cmds": [ { "cmdId": 9, "type": "MARK_NOTIFICATIONS_AS_READ", "notifications": ["notification-uuid-1", "notification-uuid-2"] } ]}Mark all as read:
{ "cmds": [{ "cmdId": 10, "type": "MARK_ALL_NOTIFICATIONS_AS_READ" }] }Legacy telemetry subscriptions
Section titled “Legacy telemetry subscriptions”These v1 commands subscribe to a single entity’s telemetry or attributes directly (without the Entity Data Query):
Attributes:
{ "cmds": [ { "cmdId": 11, "type": "ATTRIBUTES", "entityType": "DEVICE", "entityId": "device-uuid", "keys": "temperature,humidity", "scope": "SERVER_SCOPE" } ]}Time series:
{ "cmds": [ { "cmdId": 12, "type": "TIMESERIES", "entityType": "DEVICE", "entityId": "device-uuid", "keys": "temperature", "startTs": 1704067200000, "timeWindow": 3600000, "interval": 60000, "limit": 100, "agg": "AVG" } ]}Time series history (one-time fetch, no subscription):
{ "cmds": [ { "cmdId": 13, "type": "TIMESERIES_HISTORY", "entityType": "DEVICE", "entityId": "device-uuid", "keys": "temperature", "startTs": 1704067200000, "endTs": 1704153600000, "interval": 3600000, "limit": 100, "agg": "AVG" } ]}Aggregation types: NONE, AVG, MIN, MAX, SUM, COUNT.
Unsubscribing
Section titled “Unsubscribing”For v2 commands (Entity Data, Alarm Data, etc.), send an unsubscribe command with the same cmdId:
{ "cmds": [ { "cmdId": 1, "type": "ENTITY_DATA_UNSUBSCRIBE" }, { "cmdId": 4, "type": "ALARM_DATA_UNSUBSCRIBE" } ]}Unsubscribe types: ENTITY_DATA_UNSUBSCRIBE, ENTITY_COUNT_UNSUBSCRIBE, ALARM_DATA_UNSUBSCRIBE, ALARM_COUNT_UNSUBSCRIBE, ALARM_STATUS_UNSUBSCRIBE, NOTIFICATIONS_UNSUBSCRIBE.
For v1 commands (Attributes, Time Series), resend the original command with "unsubscribe": true.
Complete message flow
Section titled “Complete message flow”A typical session:
- Open WebSocket connection to
wss://host/api/ws - Authenticate — send
authCmdwith JWT token - Subscribe — send one or more commands in
cmds - Receive initial data — server responds with full result
- Receive updates — server pushes changes as they happen
- Unsubscribe — send unsubscribe command when done
- Close connection
// 1. Auth + subscribe in one message{ "authCmd": { "cmdId": 0, "token": "JWT_TOKEN" }, "cmds": [ { "cmdId": 1, "type": "ENTITY_COUNT", "query": { "entityFilter": { "type": "entityType", "entityType": "DEVICE" }, "keyFilters": [] } } ]}
// 2. Server responds with count// { "cmdId": 1, "errorCode": 0, "cmdUpdateType": "COUNT_DATA", "count": 42 }
// 3. Server pushes update when count changes// { "cmdId": 1, "errorCode": 0, "cmdUpdateType": "COUNT_DATA", "count": 43 }
// 4. Unsubscribe{ "cmds": [{ "cmdId": 1, "type": "ENTITY_COUNT_UNSUBSCRIBE" }] }See also
Section titled “See also”- Entity Data Query API — entity filters, key filters, and query format used by
ENTITY_DATAandENTITY_COUNT - Alarm Query API — alarm-specific filters used by
ALARM_DATA,ALARM_COUNT, andALARM_STATUS - Live Telemetry via WebSocket — a ready-to-run Node.js script that authenticates and subscribes to real-time device telemetry