Skip to main content
Version: 1.0.0

WebSocket API

The TwinEdge WebSocket API provides real-time data streaming for low-latency applications.

Overview

WebSocket connections enable:

  • Real-time telemetry updates
  • Live alert notifications
  • ML prediction streaming
  • Device status changes

Connection

Endpoint

wss://api.twinedgeai.com/v1/ws

Authentication

Include your API key as a query parameter or in the first message:

Query Parameter:

const ws = new WebSocket('wss://api.twinedgeai.com/v1/ws?token=YOUR_API_KEY');

First Message:

const ws = new WebSocket('wss://api.twinedgeai.com/v1/ws');

ws.onopen = () => {
ws.send(JSON.stringify({
type: 'authenticate',
token: 'YOUR_API_KEY'
}));
};

Connection Example

JavaScript:

const ws = new WebSocket('wss://api.twinedgeai.com/v1/ws?token=YOUR_API_KEY');

ws.onopen = () => {
console.log('Connected to TwinEdge WebSocket');

// Subscribe to telemetry
ws.send(JSON.stringify({
type: 'subscribe',
channel: 'telemetry',
filters: {
asset_id: 'Pump_001'
}
}));
};

ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};

ws.onerror = (error) => {
console.error('WebSocket error:', error);
};

ws.onclose = () => {
console.log('Disconnected from TwinEdge WebSocket');
};

Python:

import asyncio
import websockets
import json

async def connect():
uri = "wss://api.twinedgeai.com/v1/ws?token=YOUR_API_KEY"

async with websockets.connect(uri) as ws:
# Subscribe to telemetry
await ws.send(json.dumps({
"type": "subscribe",
"channel": "telemetry",
"filters": {
"asset_id": "Pump_001"
}
}))

# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data}")

asyncio.run(connect())

Message Format

Client Messages

Messages sent from client to server:

{
"type": "subscribe|unsubscribe|ping",
"channel": "channel_name",
"filters": {},
"request_id": "optional-id-for-tracking"
}

Server Messages

Messages sent from server to client:

{
"type": "data|event|error|pong|subscribed|unsubscribed",
"channel": "channel_name",
"data": {},
"timestamp": "2026-01-06T10:00:00Z",
"request_id": "echoed-if-provided"
}

Channels

Telemetry Channel

Real-time sensor data updates.

Subscribe:

{
"type": "subscribe",
"channel": "telemetry",
"filters": {
"asset_id": "Pump_001",
"tags": ["temperature", "vibration_x"]
}
}

Received Data:

{
"type": "data",
"channel": "telemetry",
"data": {
"asset_id": "Pump_001",
"tag_name": "temperature",
"value": 65.5,
"quality": "good",
"timestamp": "2026-01-06T10:00:00Z"
}
}

Alerts Channel

Real-time alert notifications.

Subscribe:

{
"type": "subscribe",
"channel": "alerts",
"filters": {
"severity": ["critical", "warning"]
}
}

Received Data:

{
"type": "event",
"channel": "alerts",
"data": {
"event": "alert_triggered",
"alert": {
"id": "alert-123",
"name": "High Temperature",
"severity": "warning",
"asset_id": "Pump_001",
"value": 85.2,
"threshold": 80,
"triggered_at": "2026-01-06T10:00:00Z"
}
}
}

Predictions Channel

Real-time ML predictions.

Subscribe:

{
"type": "subscribe",
"channel": "predictions",
"filters": {
"model_id": "model-456"
}
}

Received Data:

{
"type": "data",
"channel": "predictions",
"data": {
"model_id": "model-456",
"asset_id": "Pump_001",
"prediction": "normal",
"confidence": 0.94,
"anomaly_score": 0.12,
"timestamp": "2026-01-06T10:00:00Z"
}
}

Device Status Channel

Fleet device status changes.

Subscribe:

{
"type": "subscribe",
"channel": "devices",
"filters": {
"group_id": "production"
}
}

Received Data:

{
"type": "event",
"channel": "devices",
"data": {
"event": "device_status_changed",
"device": {
"id": "device-789",
"name": "Edge Device 1",
"status": "offline",
"last_seen_at": "2026-01-06T09:55:00Z"
}
}
}

OTA Deployments Channel

OTA deployment progress updates.

Subscribe:

{
"type": "subscribe",
"channel": "ota",
"filters": {
"deployment_id": "dep-123"
}
}

Received Data:

{
"type": "event",
"channel": "ota",
"data": {
"event": "device_updated",
"deployment_id": "dep-123",
"device_id": "device-789",
"status": "completed",
"progress_percent": 100
}
}

Subscription Management

Subscribe to Multiple Channels

{
"type": "subscribe",
"channel": "telemetry",
"filters": {"asset_id": "Pump_001"}
}
{
"type": "subscribe",
"channel": "alerts"
}

Unsubscribe

{
"type": "unsubscribe",
"channel": "telemetry"
}

List Subscriptions

{
"type": "list_subscriptions"
}

Response:

{
"type": "subscriptions",
"data": [
{"channel": "telemetry", "filters": {"asset_id": "Pump_001"}},
{"channel": "alerts", "filters": {}}
]
}

Connection Management

Heartbeat/Ping

Keep connection alive with ping/pong:

{
"type": "ping"
}

Response:

{
"type": "pong",
"timestamp": "2026-01-06T10:00:00Z"
}

Automatic Reconnection

Implement automatic reconnection:

class TwinEdgeWebSocket {
constructor(token) {
this.token = token;
this.reconnectDelay = 1000;
this.maxReconnectDelay = 30000;
this.connect();
}

connect() {
this.ws = new WebSocket(`wss://api.twinedgeai.com/v1/ws?token=${this.token}`);

this.ws.onopen = () => {
console.log('Connected');
this.reconnectDelay = 1000; // Reset delay
this.resubscribe();
};

this.ws.onclose = () => {
console.log(`Reconnecting in ${this.reconnectDelay}ms...`);
setTimeout(() => this.connect(), this.reconnectDelay);
this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);
};

this.ws.onmessage = (event) => {
this.handleMessage(JSON.parse(event.data));
};
}

resubscribe() {
// Re-subscribe to channels after reconnect
this.subscriptions.forEach(sub => {
this.ws.send(JSON.stringify(sub));
});
}
}

Connection Limits

TierMax ConnectionsMax Subscriptions
Starter510
Professional2050
EnterpriseUnlimitedUnlimited

Error Handling

Error Messages

{
"type": "error",
"error": {
"code": "subscription_error",
"message": "Invalid filter: asset_id is required",
"request_id": "req-123"
}
}

Error Codes

CodeDescription
authentication_errorInvalid or expired token
subscription_errorInvalid subscription request
rate_limitedToo many messages
internal_errorServer error

Handling Errors

ws.onmessage = (event) => {
const message = JSON.parse(event.data);

if (message.type === 'error') {
console.error('WebSocket error:', message.error);

if (message.error.code === 'authentication_error') {
// Refresh token and reconnect
this.refreshToken().then(() => this.connect());
}
return;
}

// Handle normal messages
this.handleData(message);
};

Rate Limiting

Message Rate Limits

TierInboundOutbound
Starter10/sec100/sec
Professional50/sec500/sec
Enterprise200/sec2000/sec

Backpressure Handling

When receiving too much data:

let messageQueue = [];
let processing = false;

ws.onmessage = (event) => {
messageQueue.push(JSON.parse(event.data));

if (!processing) {
processQueue();
}
};

async function processQueue() {
processing = true;

while (messageQueue.length > 0) {
const message = messageQueue.shift();
await handleMessage(message);
}

processing = false;
}

Best Practices

Connection Management

  1. Single connection per client

    • Reuse connections, don't open multiple
  2. Handle disconnections gracefully

    • Implement exponential backoff reconnection
    • Queue messages during disconnection
  3. Monitor connection health

    • Send periodic pings
    • Implement connection timeout detection

Message Handling

  1. Process messages asynchronously

    • Don't block on message handling
    • Use a message queue if needed
  2. Filter at the source

    • Use subscription filters to reduce traffic
    • Only subscribe to needed channels
  3. Handle message ordering

    • Messages may arrive out of order
    • Use timestamps for ordering if critical

Security

  1. Token rotation

    • Rotate tokens periodically
    • Handle token refresh without disconnection
  2. Validate messages

    • Always parse JSON safely
    • Validate message structure

SDK Support

JavaScript SDK

import { TwinEdgeClient } from '@twinedge/sdk';

const client = new TwinEdgeClient({ apiKey: 'YOUR_API_KEY' });

// Subscribe to telemetry
client.telemetry.subscribe({
assetId: 'Pump_001',
tags: ['temperature'],
onData: (data) => console.log(data)
});

// Subscribe to alerts
client.alerts.subscribe({
severity: ['critical'],
onAlert: (alert) => console.log(alert)
});

Python SDK

from twinedge import TwinEdgeClient

client = TwinEdgeClient(api_key="YOUR_API_KEY")

# Subscribe to telemetry
async def on_telemetry(data):
print(f"Telemetry: {data}")

await client.telemetry.subscribe(
asset_id="Pump_001",
tags=["temperature"],
callback=on_telemetry
)

Next Steps