API Tokens
The dashboard's API is normally reached by the dashboard itself, with a session cookie a browser holds. An API token is the other way in: a long-lived secret a program of your own sends with every request — a script, a status display in the hallway, a nightly export, anything that has no browser to sign in with.
A token belongs to one account, the one that created it. It is not a service account and not a second set of permissions: it is that person, without the browser.
Creating one
Profile → API tokens, a tab of its own on the profile page. Every account may create tokens for itself; there is nothing to enable and no administrator involved.
The form asks for two things:
- a name, which appears nowhere but this list. It is what you read months later when deciding which of four tokens to revoke, so name it after the program, not after the day.
- an expiry date, optional. Left empty, the token works until it is revoked.
The token's value is shown once, immediately after creating it, with a copy button. It is never shown again and cannot be recovered — only the hash of it is stored, so the dashboard itself cannot tell you what it was. Lose it and the answer is to revoke that token and create another.
Using one
The program sends the value as an ordinary bearer token:
Authorization: Bearer selv_…
For example:
curl -H "Authorization: Bearer $SELVARA_TOKEN" \
https://selvara.example.com/api/systems
Every endpoint the interface uses accepts this. The token is checked before the cookie, so a request that carries one is answered as that token even if a session cookie happens to be there too.
Keep the value out of the repository and out of the command line where you can —
an environment variable or a file only the program's user can read. A value that
begins with selv_ in a log is a token that needs revoking.
Following changes as they happen
A program that wants to be told rather than ask again opens the WebSocket at
wss://<your-dashboard>/api/live with the same Authorization header. The
server answers {"t":"ready"}; the program then subscribes, under an id of its
own choosing:
{"t":"sub","sid":"alerts","topic":"alert","after":null}
Every alert transition the token's account may see arrives as
{"t":"msg","sid":"alerts","id":"…","data":{…}}. Passing the last id as
after on a new connection hands over what was missed while it was away, as
long as the server has not restarted in between. The server pings every 25
seconds, and closes the socket with code 4000 when the account's rights change,
4401 when the token stops working, and 1001 when it restarts.
The same socket carries every list the dashboard shows — systems.list,
alerts.counts and the rest — as {"t":"snap","sid":…,"rev":…,"data":…},
pushed again whenever it changes. Their shapes follow the dashboard and change
with it.
What a token may do
Exactly what its owner may do, decided fresh on every request.
The token carries nothing but the account's identity. The role and the customer grants are read from the database each time, the same way they are for a browser (see Users and Permissions). So:
- a token issued by a viewer reads, and is refused every write;
- a token issued by an operator may acknowledge alerts at the customers that account is granted — and stops being able to the moment a grant is withdrawn;
- promoting or demoting the account changes what its tokens may do immediately. There is nothing to reissue.
A token is therefore not a way to give somebody narrower access than their account has. If a program should only read, it belongs to an account that only reads.
Expiry and revocation
Revoke is in the list, one button per token, with a confirmation. It takes effect at once: the next request that presents that token is answered as though nobody were signed in.
Revoked and expired tokens stay in the list. That is deliberate — together with last used, the row is what tells you whether the thing was still running somewhere when you pulled it. A token that shows a last use from this morning and a program that has not complained is a program still to be found.
Last used is not written on every single request. It is refreshed at most every few minutes, because a program polling every few seconds would otherwise cost a database write per call to record something nobody reads that often. Read it as "in use around then", not as a request log.
What a token cannot do
Tokens are managed from the browser only. A token cannot create another token and cannot revoke one — those endpoints accept the session cookie and nothing else. Without that, revoking a leaked token would achieve very little: whoever held it would already have minted a replacement with an expiry of their own choosing, and the owner's list would be the only place it ever appeared.
A token is also not a sign-in. It authorises API requests; it does not open the interface, and it does not skip two-factor authentication for anyone.
Guessing
The bearer path is rate-limited per client address, so a run of wrong values from one place stops being answered. A verification that succeeds clears that counter, which is why a program polling on a short interval never runs into it.
If a program starts getting 401 answers in bursts, check that it is not sharing an address with something retrying a stale token.