Skip to content

HTTP Endpoints

This reference is aligned with server/src/routes/http.ts.

Application JSON endpoints use the root-absolute /api/v1/ namespace. This is a hard cut: the former unprefixed application paths are not aliases. Operational and device-facing paths remain outside that namespace, including /ws, /.well-known/jwks.json, /eink/display, /lld/*, /grafana/*, and /integration/docs.

Auth labels in this page:

  • None: no auth
  • Auth: authenticated user
  • Admin: admin-only
  • Token/Auth: navigation token or authenticated user

Authentication and users

MethodsPathAuth
GET/.well-known/jwks.jsonNone
POST/api/v1/loginNone
POST/api/v1/registerAdmin
POST/api/v1/change-passwordAuth
GET, DELETE/api/v1/users/:userIdAdmin
GET/api/v1/usersAdmin

Interface templates

MethodsPathAuth
GET, POST/api/v1/interface-templatesAdmin
GET, PUT, DELETE/api/v1/interface-templates/:idAdmin
POST/api/v1/interface-templates/:id/cloneAdmin
GET/api/v1/user/sessionAuth

POST /interface-templates requires name, role (user or maintenance), and a versioned definition. A template's role is immutable after creation. PUT updates only the name and definition; clone to create a copy for another role.

Clone accepts name, role, and optional remove_incompatible. A cross-role clone returns 409 with incompatible_components until explicit removal is requested.

The visual designer's live preview uses the internal X-SafeCall-Preview-User-Id header. It is accepted only with an administrator JWT, only for the allowlisted component GET endpoints, and resolves the selected user's normal role and location scope. It is rejected for writes, exports, unrelated routes, and WebSockets. This header is an internal UI mechanism, not a general integration API.

Beacons and gateways

Path segments historically named :mac (or tracking :id) for asset lookup must be asset_uid (Phase 6c). Device MAC remains the wire identity for MQTT/gmac and replace-device bodies. Gateways also expose asset_uid (GW-…); admin MAC changes use replace-device (chunk 7c). E-ink displays expose asset_uid (EK-… / LEGACY-…); poll stays GET /eink/display?mac= (chunk 7d). Layout cells bind to the sensor asset_uid, not the device MAC.

MethodsPathAuth
GET/api/v1/beacon/:mac/infoAdmin (:mac = asset_uid)
GET/api/v1/assets/:asset_uidAdmin
GET/api/v1/assets/:asset_uid/infoAdmin
GET/api/v1/beacon/:id/intervalsAuth
GET, POST, DELETE/api/v1/beacon/:idAdmin for mutating methods (MAC not editable via POST; use replace-device)
POST/api/v1/beacon/:id/replace-deviceAdmin (optional replaced_at + retire_donor for a backdated sensor split)
POST/api/v1/beacon/:id/replace-device/planAdmin (preview keep/move counts for a backdated sensor replace)
POST/api/v1/beacon/:id/merge/planAdmin (ordered source_ids; read-only preview)
POST/api/v1/beacon/:id/mergeAdmin (irreversible source retirement + history stitch)
GET/api/v1/beacon/:id/assignmentsAdmin
POST/api/v1/assets/replace-device/batchAdmin
GET/api/v1/devicesAdmin (query: status, calibration=due|expired|ok, asset_kind=beacon|gateway|eink|all)
GET/api/v1/beacons/:limitAdmin
GET, POST/api/v1/beaconsAuth, Admin for POST
GET, POST, DELETE/api/v1/gateway/:idAdmin for mutating methods (MAC not editable via POST; use replace-device)
POST/api/v1/gateway/:id/replace-deviceAdmin
GET, POST/api/v1/gatewaysAuth, Admin for POST
GET, POST/eink/displayNone (device poll ?mac=)
GET/api/v1/eink/displaysAdmin
POST, DELETE/api/v1/eink/display/:idAdmin
POST/api/v1/eink/display/:id/replace-deviceAdmin
POST/api/v1/eink/display/:id/stateAdmin

Locations, logs, and events

MethodsPathAuth
GET, POST/api/v1/locationsAuth, Admin for POST
GET/api/v1/logsAuth
GET/api/v1/eventsAuth
GET/api/v1/events/exportAdmin

Maps

MethodsPathAuth
GET/api/v1/maps/overviewAuth
GET/api/v1/maps/imageAuth
GET/api/v1/maps/:id/overviewAuth
GET/api/v1/maps/:id/zonesAuth
GET/api/v1/maps/:id/gatewaysAuth
GET, POST, DELETE/api/v1/map/:idAdmin for mutating methods
POST/api/v1/maps/uploadAdmin
GET, POST/api/v1/mapsAuth, Admin for POST

LLD and status

MethodsPathAuth
GET/lld/beaconsNone ({#ASSET_UID}, {#MAC} = current device)
GET/lld/gatewaysNone ({#ASSET_UID}, {#MAC} = current device)
GET/api/v1/versionNone
GET/api/v1/status/kissAuth
GET/api/v1/status/mqttAuth
GET/api/v1/status/dashboardAuth
POST/api/v1/status/recheckAdmin

GET /status/mqtt and GET /status/kiss read the cached dashboard snapshot (no live KISS login). GET /status/dashboard returns MQTT, KISS, ntfy, fleet counts, and software-detected issues. POST /status/recheck with { "target": "mqtt" | "kiss" | "ntfy" } forces that probe and returns the snapshot. Dashboard and recheck responses are Cache-Control: no-store.

ntfy health checks and all notification POSTs use a bounded curl transport (not Bun fetch). The ntfy object keeps a summary ok / message plus independent reachability and delivery probes (ok, checked_at, http_status, duration_ms, error_code, message) and transport: "curl". Periodic probes update reachability only; Recheck updates both; site publishes update delivery. A successful publish does not hide a failed health check, and vice versa.

Import and deploy

MethodsPathAuth
GET/api/v1/import/beaconsAdmin
GET/api/v1/import/gatewaysAdmin
POST/api/v1/deployNone

Tracking

MethodsPathAuth
GET/api/v1/tracking/start/:algAdmin
GET/api/v1/tracking/stopAdmin
GET/api/v1/tracking/statusAuth
GET/api/v1/tracking/algorithms/currentAuth
GET/api/v1/tracking/algorithmsAuth
GET/api/v1/tracking/:idAuth (non-admin: active trackable assets only; admins: any asset_uid; :id = asset_uid)

Simple-user RTLS (read-only)

These routes require the rtls server feature. They return 400 when RTLS is disabled.

MethodsPathAuth
GET/api/v1/user/rtls/trackable-beaconsAuth
GET/api/v1/user/rtls/beacons/:mac/zone-intervalsAuth (:mac = asset_uid)

Query parameters for zone intervals: limit (default 30, max 200), cursor (offset into newest-first interval list; next_cursor in the response is the value to pass for the next page, or null when exhausted).

Integration API (external systems)

Versioned read-only API for api-role accounts (admins may also call it); see the Integration API reference. Interactive Swagger UI docs are self-hosted by the server.

MethodsPathAuth
GET/api/v1/integration/beaconsapi or Admin
GET/api/v1/integration/beacons/locationsapi or Admin
GET/api/v1/integration/beacons/:mac/locationapi or Admin (:mac = asset_uid, Phase 6c)
GET/api/v1/integration/alertsapi or Admin
GET/api/v1/integration/zonesapi or Admin
GET/api/v1/integration/openapi.jsonNone
GET/integration/docsNone
GET/integration/docs/:filenameNone
MethodsPathAuth
GET, POST/api/v1/floorsAuth, Admin for POST
GET, POST, DELETE/api/v1/floor/:idAdmin for mutating methods
GET, POST/api/v1/floor/:id/nodesAdmin for POST
POST, DELETE/api/v1/node/:idAdmin
GET, POST/api/v1/floor/:id/edgesAdmin for POST
POST, DELETE/api/v1/edge/:idAdmin
GET, POST/api/v1/floor/:id/graphAuth for GET, Admin for POST
GET, POST/api/v1/navigation/tokensAdmin
DELETE/api/v1/navigation/token/:idAdmin
GET/api/v1/navigation/mobile-keyAuth
GET/api/v1/navigation/mobile/snapshotToken/Auth
GET/api/v1/navigation/mobile/catalogToken/Auth
GET/api/v1/navigation/mobile/project/:idToken/Auth
GET/api/v1/navigation/project/:idToken/Auth
GET/api/v1/navigation/project/:id/shaToken/Auth
GET/api/v1/navigation/floor/:id/mapToken/Auth
POST/api/v1/navigation/pathfindToken/Auth

Features, sensors, and Grafana datasource

MethodsPathAuth
GET/api/v1/featuresAuth
GET, PATCH/api/v1/settingsAdmin
GET/api/v1/sensors/alertsAdmin
GET/api/v1/sensors/devicesAuth
GET/api/v1/sensors/historyAuth

Long since/until spans are downsampled on the server (latest reading per time bucket per device and metric) so responses stay bounded; short spans return raw rows (subject to a row cap). | GET | /grafana | Localhost or Auth | | POST | /grafana/search | Localhost or Auth | | POST | /grafana/metrics | Localhost or Auth | | POST | /grafana/query | Localhost or Auth |

Static frontend assets

MethodsPath
GET/
GET/index.html
GET/css/:filename
GET/js/:filename
GET/images/:filename
GET/webfonts/:filename