Fleet Custom KPI WebSocket
A WebSocket transport for live, low-rate Custom KPI values from fleet robots. Messages are UTF-8 JSON text frames. Cloud and Local currently expose different JSON envelopes, so use the contract for the environment you connect to.
Flow
- Cloud
- Local
- Log in with
POST /auth/login. - Open the fleet WebSocket.
- Parse each text frame as
FleetEventInfoDtoJSON. - Read
robotsMessage.messages[].customKpiBatch.items[].
- Log in with
POST /auth/login. - Open the WebSocket on the local fleet-manager Agent.
- Parse each text frame as JSON.
- Read
updates[].
Endpoint
- Cloud
- Local
wss://api.cognimbus.com/apigateway/v2/fleets/{fleetId}/custom-kpis?token=<token>
Replace {fleetId} with the fleet id from your organization. For the Asia region, use
api.ap1.cognimbus.com.
ws://<agent-host>:19992/apigateway/v2/fleets/local-fleet/custom-kpis?access_token=<token>
local-fleet is the supported local fleet id. Use wss:// only when the client trusts the Agent
certificate. Current Agents also accept /custom-kpis/connect as a route alias.
The request must be a WebSocket upgrade. Browser clients put the token in the query string because
the WebSocket constructor cannot set an Authorization header. Remove the leading bearer prefix
from the login response before constructing the URL.
Payload
- Cloud
- Local
The current Cloud frame uses the scalar FleetEventInfoDto shape:
{
"robotsMessage": {
"messages": [
{
"id": "robot-1",
"name": "AMR-01",
"customKpiBatch": {
"items": [
{
"metric": {
"name": "battery",
"customKpi": {
"setting": {
"id": "battery",
"label": "Battery",
"icon": "battery",
"description": "Battery level"
},
"value": { "doubleValue": 87.5 }
}
}
}
]
}
}
]
}
}
The Local frame is data-only:
{
"updates": [
{
"basicData": { "id": "robot-1", "name": "AMR-01" },
"updateTime": "2026-08-02T10:15:30Z",
"metric": {
"name": "robot_pose",
"dataType": "Nimbus.Messages.geometry_msgs.Pose",
"value": {
"position": { "x": 1.25, "y": -2.5, "z": 0.0 },
"orientation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }
}
}
}
]
}
metric.value is a native JSON scalar or object. The Agent decodes structured KPI protobuf values,
so Local Fleet KPI clients do not need Nimbus protobuf descriptors. KPI state, status, settings,
regular telemetry, connectivity events, resources, and raw MessageStream envelopes are not part of
this frame.
Local Browser Example
async function connectFleetCustomKpis(baseUrl, userToken) {
const response = await fetch(`${baseUrl}/apigateway/v2/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userToken })
});
if (!response.ok) throw new Error(`login failed: ${response.status}`);
const token = (await response.json()).token.replace(/^bearer\s+/i, '');
const url = new URL(baseUrl);
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
const socket = new WebSocket(
`${url.origin}/apigateway/v2/fleets/local-fleet/custom-kpis?access_token=${encodeURIComponent(token)}`
);
socket.onmessage = event => {
const frame = JSON.parse(event.data);
for (const update of frame.updates) {
console.log(update.basicData.id, update.metric.dataType, update.metric.value);
}
};
return socket;
}
Delivery Semantics
- Delivery is live and best-effort; this is not a replay API.
- Slow clients can drop frames, and reconnect does not recover missed values.
- Custom KPI collection normally runs once per second.
- The gateway does not resample, interpolate, or increase pose frequency.
For higher-rate data, use Data Streams in Cloud or the Local Live Stream WebSocket.
Common Errors
400: the request is not a WebSocket upgrade.401: the token is missing, expired, or invalid.404: the fleet id is not available. Local clients must uselocal-fleet.- Local browser close code
1006: the browser may not trust thewss://certificate.