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.
| Credential | Prefix | Secret? | Use it for |
|---|---|---|---|
| Tenant ID | atr_ | No — public | Identifying your tenant on every call via X-Tenant-Id |
| App login secret | alcs_ | Yes | Your 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 authreads | client_id | Optional | Standard OIDC with the authreads-hosted login page |
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.
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.
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_xxxxxxxxxxxxCreate 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.
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.
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.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.
| Value | In 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).