Skip to main content

REST API

GEM exposes a REST API for configuration reads/writes and for issuing commands. It's mounted under /api and is enabled by rest_api: true in gem.json.

Authentication

Obtain a session token, then send it on subsequent requests.

MethodPathAuthPurpose
POST/api/tokencredentialsObtain a session token.
POST/api/logouttokenRevoke the current token.
GET/api/metokenCurrent user identity and roles.
GET/api/healthnoneLiveness check (unauthenticated).
GET/api/versionnoneController version (public).

Requests other than the public ones require a valid token; without one the API returns 401 unauthorized.

Commands — /api/control/:action

POST only (other methods return 405). Two actions are supported, each gated by the matching RBAC permission:

ActionBodyMaps to
commanda command payload ({ device, zone, action, level, … })GemServer.command(body)
macroa macro reference ({ macro_id } or { macro })GemServer.macro(body)
curl -X POST https://<host>/api/control/command \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"zone": 12, "action": "on", "level": 100}'

A caller lacking the command / macro permission gets 403.

Data — /api/data/:entity

CRUD over configuration entities (device, zone, macro, …).

  • GET — read. Query-string parameters become a where filter (numeric-looking values are coerced to numbers). Requires the query permission.
  • POST / PUT / DELETE — write. The JSON body carries the payload.
# all zones in subsystem 11
curl "https://<host>/api/data/zone?subsystem_id=11" \
-H "Authorization: Bearer <token>"

Errors

StatusMeaning
400Malformed/invalid body.
401Missing or invalid session token.
403Authenticated but the role denies this action.
405Wrong method (e.g. non-POST to /api/control).

:::note The WebSocket API is the richer surface REST covers data CRUD and commands. For real-time state, subscriptions, attributes, and the full set of operations, use the WebSocket API — both are gated by the same RBAC actions. :::