API tokens
An API token is how a script authenticates to the public API. It belongs to you, it is pinned to the team you were in when you minted it, and it carries the scopes you asked for.
Minting and revoking need your dagweave session, not a token. A token can never mint another token, so widening what your automation can reach always costs a sign-in.
Minting one
Section titled “Minting one”POST /api/tokens, signed in:
curl -X POST https://api.dagweave.com/api/tokens \ -H "Content-Type: application/json" \ -H "X-Requested-With: dagweave" \ -b "__Host-dagweave_session=$DAGWEAVE_SESSION" \ -d '{"name":"run dashboard","scopes":["runs:read"],"expiresInDays":90}'name is a label to help you tell your tokens apart. scopes is required and
takes one or more of the scope names; a name that is not one of
them is a 400, and so is an empty list. Scope names are lowercased and
de-duplicated before they are stored. expiresInDays is optional and runs from
1 to 730. Leave it out and the token lives until you revoke it.
The write scopes are the ones to be careful with: runs:write starts a run on a
real cluster, workflows:write saves over a stored workflow, and
workflows:delete removes one. Put them only on a token that has to do that.
The X-Requested-With header is required on the cookie-authenticated routes
that change something, which is what minting and revoking are. Its value does
not matter, only its presence. Nothing under /api/v1 needs it: those routes
read a bearer token and never a cookie, so a cross-site form post carries no
credential to spend.
You get one look at it
Section titled “You get one look at it”The 201 response is the only place the plaintext ever appears:
{ "id": "...", "name": "run dashboard", "teamId": "...", "scopes": ["runs:read"], "createdAt": "2026-07-25T09:00:00Z", "expiresAt": "2026-10-23T09:00:00Z", "token": "dwk_..."}Copy token into your secret store now. dagweave keeps only its SHA-256, the
same way it stores session and invite tokens, so there is no way to show it to
you again. Listing your tokens later returns neither the plaintext nor the
stored hash.
A token is 256 random bits in base64url behind a dwk_ prefix. The prefix is
there so a secret scanner, or a person reading a support ticket, recognises a
dagweave key on sight.
Listing and revoking
Section titled “Listing and revoking”GET /api/tokens returns your tokens, newest first, revoked ones included. Each
row carries id, name, teamId, scopes, and createdAt, plus expiresAt,
lastUsedAt, and revokedAt once those apply.
lastUsedAt is rewritten at most once an hour. It tells you whether a token is
still in use, not the minute of its last call.
DELETE /api/tokens/{id} revokes a token and answers 204. Revocation bites on
the very next request, because every call re-reads the token’s row. You can only
revoke your own tokens; someone else’s id comes back 404.
Both minting and revoking are written to the audit log, so a token appearing out of nowhere is visible. The plaintext is never in the audit detail.
Checking what is left of your budget
Section titled “Checking what is left of your budget”GET /api/tokens/usage, signed in, reports what the public API
would allow you right now:
{ "windowSeconds": 60, "user": {"limit": 300, "remaining": 288, "reset": "2026-07-25T09:01:00Z"}, "team": {"limit": 1200, "remaining": 1102, "reset": "2026-07-25T09:01:00Z"}}It peeks the very counters /api/v1 charges, so asking never spends a request
of its own.
Teams and expiry
Section titled “Teams and expiry”A token resolves to the team you were in when you minted it, and it stays there.
Leave that team and the token stops working. Point one at a team you are not a
member of and every call is a 403.
To rotate, mint the replacement, move your script onto it, then revoke the old one. Both work at once, so nothing goes dark in between.