Skip to content

API tokens

A session comes from a person signing in with Zoho and lasts eight hours. That is wrong for a CI pipeline, so orgs can mint tokens instead.

The API tokens tab. The secret appears once, at creation, and never in the list.

An administrator, signed in, creates a token under org settings → API tokens, with a name and an optional expiry.

The secret is shown once. The server keeps only a hash of it, so a token that is lost is replaced, not recovered. Copy it into your secret store before you close the dialog.

Give it a name that says where it is used — CI — config push, nightly sync — because in six months the token list is the only record of what is holding each one.

  • Act on one org, with the admin role, as the member who created it.
  • Reach every route a session can, with three exceptions below.
  • Live indefinitely, unless you gave it an expiry.

Send it exactly like a session:

Authorization: Bearer slo_…

GET /auth/me reports via: "token", so a client can tell which kind of bearer it is holding.

Three routes are session only and refuse a token with 403 SESSION_REQUIRED:

Route Why
Mint a token A leaked token must not be able to make more.
Revoke a token Nor destroy the ones that would catch it.
Refresh a session A token that could refresh itself would never expire.

That is the whole containment story: a token that gets out can do what its org’s admin can do, and cannot entrench itself or lock you out of revoking it.

It also cannot reach another org. Every /orgs/{org}/… route checks that the org in the path is the org the token was issued for, whatever the role.

Revocation takes effect on the token’s next request, which then answers 401 TOKEN_REVOKED — a distinct code from a merely wrong token, so a pipeline can log something useful.

The row stays in the list, marked revoked, so the history of what existed remains auditable.

The same tab lists everything the org has issued, revoked ones included: the prefix, who created it, when it was last used, its expiry and its revocation. Never the secret.

Last used is the field to look at when tidying up. A token nobody has used in four months is either dead or doing something nobody remembers, and both are worth resolving.

Put it in your CI provider’s secret store and read it from the environment:

env:
SLOOSE_TOKEN: ${{ secrets.SLOOSE_TOKEN }}
Terminal window
sloose push --env production --org "$SLOOSE_ORG"

Two things not to do:

  • Do not commit it, even to a private repository. pnpm guard will not catch it for you; your secret scanner might.
  • Do not share one token across pipelines. One token per job means revoking one does not stop the others, and last used tells you something.

An expiry is optional and cannot be in the past — that is refused with EXPIRY_IN_PAST rather than creating a token that is dead on arrival.

An expired token answers 401 TOKEN_EXPIRED, again distinct from wrong-and-unknown, so the failure says what to do about it.

Setting one is good practice for anything short-lived — a migration, a contractor’s script — and usually more trouble than it is worth for a long-running pipeline, where an unnoticed expiry is just an outage.

@sloose/api-client takes a token like any other bearer:

const sloose = createClient({ token: process.env.SLOOSE_TOKEN!, environment: 'production' });

See the TypeScript client and Authentication.