Personal access tokens
Create, scope, rotate, and revoke the personal access tokens that authenticate Management API calls.
A personal access token is the only credential the Management API
accepts. It is a bearer credential that belongs to one person in one
organization, carries an explicit list of scopes,
and always expires. Personal access tokens authenticate the Management API only; they are
rejected on the portal's own API (a plain 401) and on the Inference API
(401 credential_type_mismatch).
| Property | How it works |
|---|---|
| Format | tf-pat_ followed by 43 URL-safe characters (256 bits of randomness). The fixed prefix lets secret scanners recognise a Token Factory management credential on sight. |
| Shown once | The full secret is displayed exactly once, when you create it. Afterwards the portal shows tf-pat_…a91f and the API returns a masked prefix such as tf-pat_AbCdE...a91f, plus its name, scopes, expiry and last use. |
| Hashed at rest | Token Factory stores a hash of the token, never the token itself. Nobody — including support — can show it to you again. |
| Attributable | Every token names its creator, and every call made with it is recorded in the audit log as that person using that token. A token is never anonymous and never a shared "service" identity. |
| One org | A token acts only in the organization it was created in. |
| Portal-bound | A token works only on the portal where it was created; a token from any other Token Factory portal is unknown here (401 invalid_credential). |
A token carries: id · name · prefix · scopes · created_by ·
created_at · expires_at · last_used_at · status (active ·
revoked; expiry is read from expires_at). It carries no project, no
region and no key material.
Warning
Treat a personal access token like a password. Store it in a secret manager or your CI system's secret store, never in source control, never in a URL, and never in a log line. A personal access token can reshape your organization; a project API key can only spend.
Mint policy
| Rule | Value |
|---|---|
| Who can mint | Organization Admins, in the portal only. There is no API endpoint that creates a token. |
| Re-authentication | Minting is a sensitive action. If your last sign-in is not recent, the portal asks you to re-authenticate before the token is created. |
| Note | Required, up to 64 characters, unique case-insensitively among your active tokens. A revoked token's note is free again — ci-deploy and CI-Deploy cannot both be active at once, but you can reuse a note once the token that held it is revoked. |
| Scopes | At least one, from the scope vocabulary. No wildcard; an unknown scope is refused. |
| Expiry | Mandatory. Default 90 days; the portal offers 30, 60, 90, 180 or 365. Maximum 365 days. There are no eternal tokens. |
| Active-token cap | 20 active tokens per user. Minting a 21st is refused (token_limit_reached) — revoke one you no longer use. |
These are portal rules: minting is not a Management API call, so a refused
mint is reported in the portal's token dialog (invalid_name,
invalid_scopes, invalid_expiry, token_name_taken,
token_limit_reached), not in the Management API error envelope.
Why mandatory expiry: a standing credential with no review point is how organizations fail their own access reviews. Renewal is "mint the successor, revoke the predecessor", which also gives every integration a rehearsed rotation procedure.
Lifecycle
| Stage | How | Notes |
|---|---|---|
| Mint | Portal → Settings → API Tokens → Create token opens a dialog: Note, Expiration, Select scopes (a scope tree) → Generate token. Admin only, with re-authentication. | The one credential action a token can never perform itself. Sensitive scopes are flagged at selection. |
| Use | Authorization: Bearer tf-pat_… on every call. | Never a query parameter, never a cookie. last_used_at updates as you use it. |
| Expire | Automatic at expires_at. | The next call fails with 401 token_expired. |
| Revoke | Portal → Revoke, or DELETE /me/tokens/{id} for your own tokens. Automatic when the owner is disabled; the tokens are deleted with the member when they are removed. | Immediate — the next call fails with 401 token_revoked (or 401 invalid_credential once the owner is removed). There is no grace window. |
| Audit | Mint (pat_create) and revoke (pat_revoke) are audited; every write made with the token records its id, name and the scope used. | See Audit log. |
A token's scopes are fixed at mint. Nothing widens a token: to grant more, mint a new token. Role changes can only narrow what a token can do (the intersection rule).
When a member is disabled or removed, every personal access token they created stops working
immediately and irreversibly. Project API keys they created are not
touched — keys are project assets; a personal access token represents a person still acting.
(Removing a member with "delete_keys": true is the explicit exception —
see Members.)
Create a token in the portal
-
Sign in to the portal as an organization Admin and open Settings → API Tokens. The card is titled Management API tokens:
Personal access tokens authenticate the Management API — provisioning keys, projects, and members programmatically. They can't make inference calls, and project API keys can't call the Management API.
-
Click Create token. This opens the Create Management API token dialog — nothing is created yet.
-
Enter a Note that says what the token is for and who runs it — for example
CI · payments-deploy. It must be unique (case-insensitively) among your active tokens. -
Choose an Expiration: 30, 60, 90, 180 or 365 days (default 90). Each option shows the calendar date the token would expire on. There is no "never" option — every token expires.
-
Choose scopes under Select scopes — a two-column tree, one row per resource group in scope order.
org,members,projectsandkeyseach show a parent row: ticking it grants both the group's:readand:writescopes, and the two child rows then show ticked and greyed out (still one scope each on the wire — read and write stay independent). The remaining groups (usage:read,billing:read,audit:read,catalog:read) are single rows. Every row shows that scope's description. The three Sensitive writes —org:write,members:write,projects:write— carry a badge, and selecting any of them shows a one-line warning below the list. Nothing is preselected. A summary strip below the list tracks how many scopes are selected and when the token would expire. -
Click Generate token. If your last sign-in is not recent, the portal asks you to confirm your identity: choose Sign in again, sign in, and you return to the dialog with your note, expiration and scopes kept — click Generate token once more to create the token.
-
The dialog switches to Token created, showing the secret with a Copy button and the token's name, expiry and scopes. Copy the secret now and store it in your secret manager — it is shown once, and the dialog ignores Escape and outside clicks so you can't lose it to a stray click. Click Done to close.
Each token then appears as a row with its name, masked prefix, creation
date, expiry and last use (tf-pat_…a91f · created Mar 20, 2026 · expires Jun 18, 2026 · last used never), its scopes, and (for active
tokens) a red Revoke button that asks you to confirm.
Tip
Every call is attributed to the token's creator. Mint automation tokens under a person who will stay responsible for that automation, and name the token after the job, not the person.
Verify a new token
The cheapest authenticated call is reading your own token list — it needs no scope:
curl https://portal.<domain>/api/v1/mgmt/me/tokens \
-H "Authorization: Bearer $TF_PAT"Rotate a token
Tokens have no grace window: mint the successor first; both work side by side until you revoke the old one. Rotation is three steps:
- Mint the successor in the portal with the same scopes and a fresh expiry.
- Deploy it — replace the secret in your CI system or secret manager and confirm one call succeeds.
- Revoke the predecessor — in the portal, or with
DELETE /me/tokens/{id}using the new token.
Put a reminder on the calendar a week before expires_at. An expired token
fails with 401 token_expired and an action telling you to mint a new one.
If a token leaks
Revoke it immediately (portal, or DELETE /me/tokens/{id}); revocation is
effective on the next call. Then read the audit log
filtered to the token owner (actor) and look for entries whose
metadata.pat_id is that token's id to see what it did. See
Incident response.