Skip to main content

WebSocket Real-time Updates

SpatialFlow provides WebSocket connections for streaming real-time device locations, geofence events, and dashboard statistics without polling.

Overview

WebSockets enable your application to receive instant updates as devices move and trigger geofence events. The following channels are available:

ChannelURLPurpose
Dashboardwss://api.spatialflow.io/ws/dashboard/events/Aggregated stats and live activity feed
Geofence Eventswss://api.spatialflow.io/ws/events/geofence/Real-time geofence entry/exit events
Workflowwss://api.spatialflow.io/ws/workflows/{workflow_id}/Live workflow status updates
Workflow Executionwss://api.spatialflow.io/ws/workflows/{workflow_id}/executions/{execution_id}/Step-by-step execution progress
Webhook Statuswss://api.spatialflow.io/ws/webhooks/status/Webhook delivery status updates

Authentication

Preferred method: Pass your JWT token via the Sec-WebSocket-Protocol subprotocol header:

Sec-WebSocket-Protocol: access_token, YOUR_JWT_TOKEN

Fallback (deprecated): Pass the token as a query parameter:

wss://api.spatialflow.io/ws/dashboard/events/?token=YOUR_JWT_TOKEN

The query parameter method is supported for backward compatibility but will be removed in a future release. Use the subprotocol method for new integrations.

Connecting

JavaScript Example

const token = 'YOUR_JWT_TOKEN';
const ws = new WebSocket(
`wss://api.spatialflow.io/ws/dashboard/events/`,
['access_token', token]
);

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

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

ws.onclose = (event) => {
console.log('Disconnected:', event.code, event.reason);
};

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

Python Example

import asyncio
import websockets
import json

async def connect():
token = "YOUR_JWT_TOKEN"
uri = "wss://api.spatialflow.io/ws/dashboard/events/"

async with websockets.connect(uri, subprotocols=["access_token", token]) as ws:
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")

Message Types

Dashboard Channel

Message TypeDescriptionPayload
dashboard_updateInitial dashboard snapshot (sent on connect){ stats: { active_geofences, active_devices, events_today, entries_today, exits_today, timestamp }, recent_events: [...], timestamp }
new_eventReal-time event push (sent for each new event){ event: { ... }, timestamp }

Geofence Events Channel

Message TypeDescriptionPayload
geofence_eventDevice entered or exited a geofence{ event: { ... }, timestamp }

Message Format

Messages are JSON objects with a type field identifying the event kind. Here is an example geofence event:

{
"type": "geofence_event",
"event": {
"device_id": "truck-005",
"geofence_id": "123e4567-e89b-12d3-a456-426614174000",
"geofence_name": "Downtown Delivery Zone",
"event_type": "entry",
"location": {
"latitude": 37.7749,
"longitude": -122.4194
}
},
"timestamp": "2026-02-05T14:30:00Z"
}

Reconnection Strategy

WebSocket connections can drop due to network issues. Implement automatic reconnection with exponential backoff:

function connectWithRetry(url, maxRetries = 10) {
let retries = 0;

function connect() {
const ws = new WebSocket(url);

ws.onopen = () => {
console.log('Connected');
retries = 0; // Reset on successful connection
};

ws.onclose = (event) => {
if (retries < maxRetries) {
const delay = Math.min(1000 * Math.pow(2, retries), 30000);
console.log(`Reconnecting in ${delay}ms...`);
retries++;
setTimeout(connect, delay);
}
};

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

return ws;
}

return connect();
}

Next Steps