Skip to content
authreads Docs

API and credentials

Create and operate credentials from one dashboard page. Choose by what the caller needs to do, not by an internal credential name.

Four credentials, four jobs

Pick by what the caller needs to do. Each has a recognizable prefix so you can tell them apart at a glance.

CredentialPrefixSecret?Use it for
Tenant IDatr_No — publicIdentifying your tenant on every call via X-Tenant-Id
App login secretalcs_YesYour own server-side login page or service (the app marked “signs users in”)
API Access (machine)ac_ / as_Yes (the as_ secret)Server-to-server Management API calls (client-credentials)
Sign in with authreadsclient_idOptionalStandard OIDC with the authreads-hosted login page
The alcs_ secret is the app login credential's public id (alc_…) plus a secret value, in the form alcs_<alc_id>.<value>. Send it as a Bearer token alongside X-Tenant-Id — see Sessions & tokens. For machine and OIDC credentials, see Management API and Sign in with authreads.

One name, everywhere.This table is the canonical naming — the admin dashboard's credential list uses the same label. If you arrived expecting a different name (a “tenant secret”, a “login password”), it's this row: the alcs_ credential that authenticates your login page or service to authreads.

If a stored value starts with atrsk_, it's a retired credential format — the earlier tenant-wide shared secret, superseded by the alcs_ app login secret above. It will not authenticate. If you find one in a config or secret manager (migrated from an older setup, for example), replace it with a freshly issued alcs_credential rather than assuming it still works or investigating further — it doesn't, and there's nothing else to find.

The app login secret's exact shape

The whole string is hashed for storage and verification, so every character is load-bearing — there is no label portion you can safely trim. The format is validated exactly:

  • Starts with alcs_, followed by the public id (alc_ plus 20 hex characters), a single . separator, then the secret material.
  • The secret material after the dot is exactly 64 hex characters.
  • Hex digits must be lowercase. An uppercase character anywhere in either segment makes the credential fail authentication — silently, with the same generic error as a wrong secret (see invalid_client).
  • Exactly one . separator — not zero, not two.
Copy and store the value exactly as shown, in full, the moment it's revealed. A clipboard tool, editor, or secret-manager import step that uppercases hex, trims whitespace, or splits the string at the dot produces a credential that looks well-formed and can never authenticate — and the failure gives no hint that formatting is the cause.

Get your Tenant ID

Open Dashboard → API and credentials. The Tenant ID (atr_…) is labelled Not a secret and can be copied into configuration as a public identifier.

AUTHREADS_TENANT_ID=atr_xxxxxxxxxxxx

Create a login password

First open Applications and enable This app signs users in only on the login surface. Then choose Create credential → Signing users in. Destination apps that only receive tokens do not need a login password and are intentionally omitted from the picker.

Running more than one product application behind a single login page or service? See Suite / multi-app tenants before you decide which application this credential belongs to — the choice has a sharp edge if that application is ever disabled.

Sign in with authreads (OIDC)

Use this when you want authreads to host the login page and hand your app a standards-compliant id_token, instead of building your own login form against an app login secret. Register the client and walk the full authorization-code + PKCE flow in Sign in with authreads → Register an OIDC application.

Store and rotate secrets

Secrets are displayed once and stored only as digests. Save a newly created or rotated value in your secret manager before closing the reveal dialog.

Rotating an app login secret or an API Access secret keeps the old value working for a 24-hour grace window. Issuing a new secret does not break existing callers — both the new and the just-rotated secret authenticate for 24 hours, so you can roll the new value through every caller without a synchronized flag-day. The admin dashboard shows the countdown on the credential (previous_secret_expires_at), and every authentication on the grace-period value is audited (app_login_credential.previous_secret_revoked / api_client.previous_secret_revokedwhen it's later force-ended). Once every caller is confirmed on the new value, end the window early from the credential's “End rollover window” action instead of waiting it out — that revocation is immediate.
This grace window applies to the alcs_ app login secret and the as_ API Access secret only. An OIDC client_secret (confidential client, see Sign in with authreads) is different: rotating it invalidates the previous value immediately, with no overlap — update every caller of that client in the same change. Never put a secret in browser code, a NEXT_PUBLIC_* variable, source control, or logs.

Account-security scopes

Grant account-security:readwhen a backend needs to list one user's active sessions, trusted devices, or renderable trusted-device policy. Grant account-security:manage only when it must end that access.

account-security:manage is dangerous: it can immediately sign a user out and remove every trusted-device bypass. It is never included in the default runtime preset; grant it explicitly and only to the backend that implements the account-security UI.

What's safe in the browser?

The rule is simple: public identifiers can ship to the browser; anything that authenticates must stay on a server you control.

ValueIn the browser?
Tenant ID (atr_)✅ Yes — public identifier
OIDC public client_id✅ Yes — public clients use PKCE, no secret
App login secret (alcs_)⛔ Never — server only
API Access secret (as_) / machine token⛔ Never — server only
OIDC client_secret (confidential client)⛔ Never — server only
NEXT_PUBLIC_*— and any bundler “public” prefix — is compiled into the JavaScript every visitor downloads. A leaked secret is typically abused within minutes. If a secret ever reaches the browser, source control, or a log: rotate it immediately, assume the old value is compromised, and move the call to your backend (the backend-for-frontend pattern).