Skip to content

HTTP and WebSocket API ​

All /api routes except login need Authorization: Bearer <jwt>. Data is always scoped to the caller's company.

Endpoints ​

ServiceMethod and pathRolePurpose
ingestionGET /ws/robot/{id}noneRobot telemetry socket
ingestionGET /healthznoneLiveness, 204
apiPOST /api/auth/loginnoneEmail and password to JWT (HS256, 8h)
apiGET /api/auth/meanyCurrent user
apiGET /api/fleet/snapshotanyLatest state of every robot
apiGET /api/fleet/inventoryany{ sites, robots } from PostgreSQL
apiGET /api/robots/{id}/history?minutes=60anyPersisted samples, oldest first, up to 720 points, window up to 24h
apiGET /api/reports/activity?hours=1anyTasks started, elevator rides, faults and average battery per hotel and robot type, window up to 24h
apiPOST /api/robotsadmin, operatorCreate a robot, 201
apiPATCH /api/robots/{id}admin, operatorUpdate any field except the id
apiDELETE /api/robots/{id}admin, operatorDelete the record and its live state, 204
apiGET /ws/fleet?token=anyArrays of changed robots every 250ms
apiGET /healthznoneLiveness, 204

Errors ​

StatusWhen
400Validation failed, unknown field, invalid JSON, unknown hotel. The body is { "error": "<reason>" }
401Missing, invalid or expired token
403Role not allowed to write
404Robot not found in the caller's company
409Robot id or serial number already exists

Robot packet (robot to ingestion) ​

json
{
  "robot_id": "muc-dlv-07",
  "status": "active",
  "telemetry": { "latitude": 48.1402, "longitude": 11.5586, "speed_mps": 1.2, "battery_pct": 84.5 },
  "current_task": "deliver_room_1204",
  "timestamp": "2026-09-24T00:00:00Z"
}
FieldRule
statusactive, charging, error or idle
latitude, longitude[-90, 90] and [-180, 180]
speed_mps[0, 50]
battery_pct[0, 100]
current_task[A-Za-z0-9_.:-], up to 128 characters
timestampRFC 3339, at most 30s in the future

Live state (API to dashboard) ​

json
{
  "robotId": "muc-dlv-07",
  "status": "active",
  "latitude": 48.1402,
  "longitude": 11.5586,
  "speedMps": 1.2,
  "batteryPct": 84.5,
  "currentTask": "deliver_room_1204",
  "timestamp": "2026-09-24T00:00:00.000Z",
  "ingestedAt": "2026-09-24T00:00:00.120Z"
}

Robot record (create body) ​

json
{
  "id": "muc-dlv-99",
  "kind": "delivery",
  "siteId": "muc",
  "model": "Courier D2",
  "serialNumber": "SN-200001",
  "firmware": "5.0.0",
  "maxSpeedMps": 1.2,
  "batteryWh": 900
}

kind is cleaning, delivery, room_service or reception. maxSpeedMps is above 0 and up to 50; batteryWh is a whole number from 1 to 100000.

Redis keys ​

KeyTypeWriterReader
robot:telemetry:livePub/Sub channelingestion-serviceorchestration-api
fleet:live_stateHash: robot id to RobotState JSONorchestration-apisnapshot endpoint