API tokens
Non-interactive credentials for CI and scripts — how they are issued, how they authenticate, and what happens when the person who made one leaves.
An API token is what CI uses instead of a password. Use one rather than sharing an account: tokens are revocable individually and their use is timestamped.
Issuing one
POST /api-tokens with a name, and optionally expiresInDays (1–3650).
The response is the only one in the product that carries the issued value. No other endpoint can return it, because no other response shape has a field that could hold one.
st_XXXXXXXX…The st_ prefix is deliberate: a token pasted into a public repository can be found by a
secret scanner — and by the person who pasted it.
On expiry
Expiry is optional because a CI token that expires unannounced breaks a pipeline at the worst possible moment. It is offered because a token that never expires is one nobody remembers to revoke. Pick knowingly.
What is stored
An HMAC-SHA-256 digest under AUTH_SECRET, exactly like a session token, plus a readable
head — the prefix and the first eight characters — so you can identify it in a list. A
database leak yields nothing usable.
Using one
A token resolves through the same global session guard a cookie does, into the same
AuthenticatedSession shape. No route has a parallel authorization path — a token can do
what the session it resolves to can do, and nothing else gets a second implementation to keep
in sync.
lastUsedAt is stamped on use.
Revoking
DELETE /api-tokens/:id revokes rather than deletes, so the audit trail keeps its
referent. A revoked token appears in the list with revokedAt set.
When someone leaves
A token's organization is stored on the token row at creation and re-validated against membership on every use. A user removed from the organization does not keep acting through a token they left behind.