Skip to main content

Authentication

Two headers on every request: a credential, and the workspace it acts in. Set them once here; every guide uses these variables.

1. Get a key​

Settings → Access → NEW KEY. Name it after the bridge or script that will hold it. The secret starts with dak_, is shown once, does not expire, and is revoked from the same list.

Or mint one from a signed-in session:

# A session token comes from signing in to the console. It lasts thirty minutes;
# a key lasts until it is revoked, which is what an unattended script wants
curl -s -X POST https://<your-backend-host>/api/keys \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "X-Workspace-Id: wsp_…" \
-H "Content-Type: application/json" \
-d '{ "name": "harbour-bridge" }' \
| jq '.data | {name, prefix, secret}'
# → { "name": "harbour-bridge", "prefix": "dak_o9yF", "secret": "dak_o9yF…" }
# copy secret now: the server keeps only a hash

2. Find the workspace​

# Every workspace this credential can act in, with your role in each
curl -s https://<your-backend-host>/api/me \
-H "Authorization: Bearer $SESSION_TOKEN" \
| jq '.data.workspaces[] | {id, name, role}'
# → { "id": "wsp_3465c050…", "name": "Harbour", "role": "owner" }

A key belongs to the workspace it was minted in, and already names it. The guides send X-Workspace-Id anyway: it is required with a session token, and a key sent with the wrong one is refused rather than quietly acting somewhere else.

3. Set the variables​

# Every integration guide uses these three, and repeats none of them
export DOME=https://<your-backend-host>/api # the deployment's API root
export KEY=dak_… # from step 1
export WS=wsp_… # from step 2

Every request then carries both headers:

# Check both work: the workspace's current environment and run state
curl -s $DOME/sim/state \
-H "X-Api-Key: $KEY" \
-H "X-Workspace-Id: $WS"
# → {"ok":true,"data":{"mode":"live","simulator":"lite","run":"idle"}}

4. Open the stream​

The event stream takes neither the key nor a token. It takes a one-time ticket, good for a minute:

# Mint a ticket with the key ...
TICKET=$(curl -s -X POST $DOME/auth/stream-ticket \
-H "X-Api-Key: $KEY" -H "X-Workspace-Id: $WS" \
| jq -r '.data.ticket') # → stk_8Fw6CVdP…

# ... and spend it opening the stream. It names the workspace for you
curl -sN "$DOME/stream?ticket=$TICKET"
# → event: snapshot the whole picture, once
# event: track_update then one event per change

Reconnecting needs a new ticket. Events: Picture & stream.

When it is refused​

AnswerMeans
401 unauthenticatedNo credential, or a key that was revoked or never issued.
400 invalid_inputA session token with no X-Workspace-Id. The error points at GET /api/me.
403 forbiddenA key sent with a workspace it does not belong to.
403 not_a_memberA session token naming a workspace you are not in.
403 on a writeA read-only role.

Every answer is { "ok": true, "data": … } or { "ok": false, "error": "…", "code": "…" }. See API overview.

Next: Running a simulation · Working with assets · Commanding assets