Skip to main content

API tokens

Creating a programmatic credential, the scopes it has to carry, the 90-day default lifetime, the health badges, and what to do the day one leaks.

Written for whoever runs IT10 min readUpdated

An API token is a long random string that stands in for a person when a script, an integration or another system calls Qorionix. It is not a session: it does not expire after thirty minutes, it does not need a second factor, and it does not care where it is used from.

The single most important sentence in this article is this one: a token carries exactly the permissions of the user who created it. Everything else follows from that.

What a token can do

The creator's role remains the outer boundary, and it is a real one. The permission model has no wildcards and no superuser bypass — a role holds a specific, enumerated set of permissions, and a check is an exact match on a resource and an action. So a token created under an account holding a narrow custom role really can only do the narrow thing, whatever scopes are written on it. See The permission model.

Scopes, and the vocabulary they have to come from

Every key must carry at least one scope, and every scope must be a real permission name from the platform's own catalogue. A scope is written resource.action — users.read, for instance — or as a wildcard covering one resource, resource.*. Anything else is refused at creation rather than stored and ignored: a name that is not in the catalogue, a string with no dot in it, and a bare * are all rejected when you try to create the key.

There is an endpoint that returns the current list of valid scopes and wildcard forms, so an integration never has to guess and never has to be updated by hand when the catalogue grows. Read it rather than transcribing a list from anywhere — including from this article, which is a snapshot and the endpoint is not.

  1. Create a dedicated account for each integration

    Not a shared one, and not a person's. When the integration misbehaves you want the audit trail to name it, and when the person leaves you do not want their departure to take the integration with them.

  2. Give that account the narrowest role that works

    Start with a role holding nothing and add permissions until the integration stops failing. A custom role begins with zero permissions by design, which makes this approach the path of least resistance rather than an act of discipline.

  3. Create the token as that account

    The token inherits the role at use time, not at creation time, so tightening the role later tightens the token too. That is the one piece of good news in this design.

  4. Write down what it is for

    The name is the only description a token carries and the only thing you will have to go on in a year. zapier-invoices-prod is a name. test is not.

Creating one, and the one-time display

A token is 64 characters of lowercase hexadecimal, generated from 32 bytes of cryptographic randomness. Only a hash of it is stored, so the value itself is genuinely unrecoverable afterwards. The creation response is the only place it ever appears — listing tokens returns the record without the secret, so a later list cannot leak it.

Alongside the hash we keep the first eight characters in clear, as a prefix, so that you can tell one token from another in a list. Copy the full value into wherever it is going before you close the screen. There is no 'show it again'.

Creation is refused if the organisation is not active, with organization is not active and HTTP 403, and requires you to be a member of the organisation you are creating it for. Every creation is audited as organization.api_key_created, recording the name, the prefix and the expiry — so the audit trail tells you a token was issued without ever recording the token.

Expiry

Every key now has an expiry date. If you do not choose one, it gets 90 days. The console offers 30, 90 or 365 days when you create a key, with 90 selected for you and described on the screen as long enough to be useful, short enough to force a rotation habit. 365 days is the maximum, and there is no longer a never-expires option to choose.

There is no rotation mechanism. Rotating means creating a second token, moving the integration over, confirming it works, then revoking the first. Do it in that order — revoking first gives you an outage instead of a rotation.

Health badges on the API keys screen

Alongside a key's basic status — Active, Revoked or Expired — the screen shows advisory badges. They are advice, not a state the platform acts on, and a key can carry more than one at once.

Rotate soon
The key expires within 14 days. It still works. This is your two-week warning to create the replacement, move the integration over and revoke the old key in that order.
Dormant
The key has not been used for 90 days — counted from the last time it was actually used, or from the day it was created if it has never been used at all. So a key created three months ago and never wired up goes dormant on its own timeline. A dormant key is usually either an integration that quietly stopped, or a credential nobody needed in the first place. Both are worth a minute of your attention.
Orphaned
Shown on the organisation-wide view only. The account the key belongs to is no longer an active member of the organisation — they left, were suspended, or are currently locked out.

Above the list is a small stat row counting how many of your organisation's keys are in each state, and a short explanatory banner for each badge — shown only when at least one key actually carries it, so an empty, healthy list stays quiet rather than lecturing you about problems you do not have.

Who can see which tokens

There are two views, and the difference matters when you are trying to answer 'what programmatic credentials exist against this organisation?'

The two ways to list tokens. The per-user view is not an inventory.
ViewShowsRequired permission
Your own tokensOnly the tokens created by the account making the request. This is what a service account uses to manage its own credentials.None beyond being signed in — it is keyed on your own identity.
The organisation's tokensEvery token issued against the organisation, whoever created it.api_keys.read, with api_keys.write to create and api_keys.delete to revoke.

The organisation-wide view exists because the per-user one cannot answer the question an administrator is actually asking: it shows only their own tokens and hides every other service account in the organisation. If you are conducting an access review, use the organisation view, and remember that a token's real privilege is the privilege of the account named on it.

Revoking one

Revoking marks the token inactive and stamps the time it happened. The record is kept rather than deleted, so the audit trail of a credential that once existed is not erased by removing it. Every authentication path checks the active flag, so revocation takes effect immediately.

You can revoke your own tokens without any special permission. Revoking somebody else's requires api_keys.delete. A token identifier that does not exist, or that belongs to another organisation, answers API key not found with HTTP 404.

What to do if a token leaks

Assume it has been used. A token is a bearer credential: anybody holding the string is the account, from anywhere, with no second factor and no session to expire. There is nothing about the token itself that limits where it can be presented from.

  1. Revoke it first, argue about it afterwards

    A revoked token that turns out to have been safe costs you a five-minute reissue. An unrevoked one that turns out not to have been safe costs considerably more. Revoke before you investigate.

  2. Work out what the token could reach

    Not what the integration used it for — what its creating account's role permits. Those are different questions and the second one is the one that matters. If the creator was an administrator, treat it as an administrator credential compromise.

  3. Read the audit log for that prefix and that account

    The prefix is recorded at creation, and actions taken by the account are recorded as they happen. Look for anything outside the integration's normal pattern, particularly role changes, new tokens and new SSO providers.

  4. Reissue under a narrower account

    A leak is the best opportunity you will get to fix the fact that the token had more privilege than the integration needed. Create the replacement under a dedicated account with a minimal role.

  5. Remove it from wherever it leaked

    Rewriting a repository's history, clearing a chat message, purging a build log. Revoking makes the string useless, but a credential lying around in a repository teaches whoever finds it that credentials are stored there.

The messages you will see

API token errors, verbatim
name and organization_id are required
organization is not active
failed to create API key
failed to list API keys
API key not found
failed to revoke API key

Nothing here tells the caller whether a token exists but belongs to somebody else — a token you may not touch and a token that does not exist answer identically. That is deliberate; the alternative turns the endpoint into a way of confirming that a given identifier is real.

What to do next

  1. List your organisation's tokens and check the account named on each one. Any token created by a personal administrator account should be reissued under a dedicated service account.
  2. Choose an expiry deliberately on the replacements rather than letting them default to 90 days, and rely on the Rotate soon badge rather than on your memory for the renewal.
  3. Read The permission model to work out the narrowest role each integration can live with, and fetch the valid scope list from the API before you write any scope into a configuration file.
  4. If you closed the creation dialog before copying a token, read One-time secrets — there is no way to retrieve it, only to revoke and reissue.

Was this article wrong?

If a procedure here does not match what you see, or a limit we described has changed, tell us and we will fix the page. Email us about this article, or see how to get help if you need an answer rather than a correction.

Everything in identity and access