API reference
Everything the console does, it does through this API. The same surface is yours: hydrate the picture, hold the stream, register assets, and command them through what each one advertises.
:::note These pages are for engineers The rest of these docs describe the product. This section documents the HTTP surface itself: routes, payloads, and the rules a well-behaved client follows. :::
Every document the API takes and returns, commented field by field, is on one page: Data model. Getting a key: Authentication. Worked curl sessions: Running a simulation, Working with assets, Commanding assets.
Base URL
All routes in this section are served under /api on your DomeCommand backend
(port 8077 by default):
https://<your-backend-host>/api
Every route under /api is authenticated and workspace-scoped. Send either a session
token as Authorization: Bearer <token> or a workspace API key as
X-Api-Key: dak_..., and name the tenant with X-Workspace-Id. A request with no
credential gets 401; a credential that does not reach the named workspace gets 403.
These take no credential: GET /, GET /health, GET /api/openapi.json, the
explorer at GET /api/docs/, and the sign-in routes POST /api/auth/login,
POST /api/auth/verify and POST /api/auth/refresh (plus POST /api/auth/dev-login on
a deployment in development mode). GET /api/stream is open to the middleware because
EventSource cannot send headers, and authenticates on a single-use ticket you fetch
first from POST /api/auth/stream-ticket. Everything else, GET /api/health included,
answers 401 without a credential.
The response envelope
Every JSON response uses one envelope. Success carries data:
{ "ok": true, "data": { "id": "…" } }
Failure carries error, a sentence that names what failed and why:
{ "ok": false, "code": "verb_not_advertised",
"error": "BLUE-04 cannot be commanded to Intercept" }
An error carries both halves. error is a sentence naming what failed, for the
person reading a log; code is a frozen ApiErrorCode for the program deciding what
to do next. Branch on code; the sentence is free to be reworded.
One route steps outside the envelope, for a format reason: GET /api/stream is
text/event-stream.
| Status | Meaning |
|---|---|
200 | The request succeeded. data holds the result. |
201 | Something was created. Location names where it now lives. |
204 | A delete succeeded. There is nothing left to describe. |
400 | The input failed validation. The error says which rule. |
401 | No credential, or one that is spent. |
403 | A credential that does not reach the named workspace, or a read-only role on a write. |
404 | The named resource is not in this workspace. |
409 | The request conflicts with current state: a verb the asset does not advertise, a plan outside the candidate set, a port already bound. |
501 | The deployment was built without the feature this route needs. |
503 | A required backing service is not configured, such as the secret store's encryption key. |
The one rule that shapes a client
Hydrate once, then hold the stream. GET /api/picture returns the whole current
state in one response and exists for exactly that moment; GET /api/stream then
delivers every change as a server-sent event. A client that polls is a client that is
always either stale or wasteful, and the console itself makes zero requests at rest.
The full contract is on Picture & stream.
The explorer
The API explorer gives every route its own page, generated from the OpenAPI document the server publishes: parameters, request and response schemas, status codes, a code sample in five languages, and a console that sends the request. What each field in those schemas means is on Data model. It has its own sidebar, one category per area, and nothing there is hand-written, so it matches the build it was generated from.
Base URL on any of those pages defaults to https://api.domecommand.ai; set it
to your own deployment before you press Send API request. The browser sends the
request itself, so the backend has to allow the origin the page is served from.
Against a deployment that does not, use the generated curl instead.
The document itself is GET /api/openapi.json. See
The OpenAPI document for generating a client from it.
What is where
| Area | Routes | Page |
|---|---|---|
| The live picture and its deltas | GET /api/picture, GET /api/tracks, GET /api/stream | Picture & stream |
| Pushing detections, reading the event log | POST /api/signals, GET /api/events | Observations & events |
| Assets, sensors, discovery, commands | /api/assets, /api/discoveries, /api/links | Assets & commands |
| Threats, the task ledger, plan approval | /api/threats, /api/tasks, /api/plans | Plans & tasks |
| Zones, regions, doctrine, rules, the line | /api/zones, /api/regions, /api/rules, /api/decision-config | Configuration |
| Scenarios, the simulator, run history | /api/scenarios, /api/sim, /api/sim/runs | Simulation |
| Signing in, workspaces, API keys | /api/auth, /api/workspaces, /api/keys | Authentication |
| The server describing itself | GET /api/openapi.json | The OpenAPI document |
| Every document, field by field | scenario, asset, command, task, observation | Data model |
| Every route, one page each | all of them | API explorer |