Skip to content
Authreads Docs

API Reference

The complete generated reference for tenant-facing Authreads APIs, including BFF account-security session, device, and policy operations. See Examples for copy-paste snippets.

Machine-readable contract: the same OpenAPI document this page renders is published at /openapi.json for code generators, API clients and assistants.

API sign-in v2 — password, proof, setup, exchange

Authenticate every call from your backend with the app login credential./api/v1/auth/login/preflight serves only v2; the optional Authreads-Login-Flow header accepts only 2. After password verification, follow next_method and alternatives: email code, authenticator, recovery code or a passkey on a verified application domain. Replace your stored flow_token after every transition. The original ten-minute expiry never extends; Back cancels the flow. Keep secrets and capabilities out of browser JavaScript, URLs and logs.

Backend-owned authenticator journey
POST /api/v1/auth/login/preflight
Authreads-Login-Flow: 2
{"email":"user@example.com","password":"…","min_acr":"urn:authreads:acr:mfa"}

POST /api/v1/auth/login/flow/verify-totp
{"flow_token":"<latest capability>","code":"<authenticator code>"}

# Only after a response containing grant:
POST /api/v1/auth/session/exchange
{"grant":"<one-time grant>"}

An unfinished response omits grant. Handle password_change_requiredwith /api/v1/auth/password/change-expired and {flow_token,new_password}, then restart sign-in. For strong_method.state Ask or Required, use/login/flow/enrol/totp/start and /confirm, or the passkey enrollment begin/finish endpoints. Only unexpired Ask permits /login/flow/remind-later. Enrollment authority is the flow; no account session is issued before setup. Setup uses the same account-wide strongest-factor rule as account security, including passkeys on another RP. Select an existing authenticator or recovery code before setup when that passkey cannot be used here. Preflight prefers an available recovery code before sending an email that cannot authorize setup; always follow the returned method. A final consumed recovery code remains repair proof; it does not become MFA evidence.

For passkeys, send the exact registered Authreads-Passkey-Origin on preflight, then call /login/flow/passkey/begin with the latest flow and origin. Forward the returned challenge options to the browser or native client and return the signed credential with its ceremony ID to /finish. Android certificate origins and Apple associated domains require verified app-domain registration; an arbitrary display domain is insufficient.

flow_superseded (409) requires a new flow; retries never issue another grant. Reverify returns 401 session_invalid for unknown, other-tenant, revoked or expired sessions. Clear the application session and require sign-in. A live same-tenant session for another app returns 403 session_app_mismatch. Respect Retry-After on 429. login_proof_rejected andlogin_method_unavailable need a server-directed proof or method change.strong_method_setup_required blocks completion until setup.fresh_authentication_required requires a fresh strongest-method sign-in; additional methods belong in authenticated account security.stronger_proof_unavailable_here means no usable repair proof is available: manage methods where the existing passkey works or use the organisation’s audited reset process.recovery_proof_required (403 on setup) means only a recovery code can authorize setup on this site: restart sign-in and choose recovery_code, or manage methods where the passkey works. A response carrying recovery_codes_exhausted: true (a sign-in with the last recovery code, or a setup it authorised) left the account with no unspent recovery codes; prompt the user to generate new ones. A malformed remembered-browser value returns 400trusted_device_invalid: discard the stored value and retry without it.app_passkey_domain_unverified and app_login_unavailable need an administrator repair. Retired endpoints return endpoint_removed with HTTP 410.

Completed v2 grants and valid end-user session responses expose acr,auth_time and cumulative amr. Contexts are orderedsingle, pwd, 2fa, mfa,phr, each prefixed with urn:authreads:acr:. Email and recovery with password reach 2fa; authenticator with password reaches mfa; a user-verified passkey reaches phr. Trusted-browser skips and enrollment bootstrap stay pwd. The proof supporting the strongest context owns auth_time; later password checks cannot make an older strong proof appear fresh. Operator tokens omit this end-user context. These values do not assert NIST AAL certification.

Request an optional min_acr on v2 preflight to restrict the proof methods. An existing password-proven app session can instead POST/api/v1/auth/login/flow/reverify with{"session_id":"<session bearer>","min_acr":"urn:authreads:acr:mfa"}. Follow the same rotating proof flow. Completion returns session_reverified:trueand fresh context without a grant; retain the original session and expiry. Passkeys require the exact verified origin at admission and ceremony calls.unmet_authentication_requirements means no configured method meets the floor; direct the user to account security setup. Trusted-device skips cannot satisfy it.

remember_device_unavailable is a 400 refusal before proof consumption; clear the option and retry with remember_device=false. Hosted OAuth publishes the same value in error_code. API and hosted offers, acceptance and token creation share one rule; reverify, Required rollout, recovery and requests above password strength cannot mint browser trust. Refresh the offer after method changes and resend.

On an actionable verification step, trusted_device_available tells you whether to offer remember-device; trusted_device_window_days uses effective policy. These fields are omitted during setup, password change, reverify and terminal responses. Test amr membership, never equality. First strong-factor enrolment returns recovery_codes once. Follow Let users manage 2FA from your app for authenticated account changes and lost-response recovery.

For a shared browser, keep a bounded, newest-first device_tokens list in backend-owned storage or an HttpOnly cookie. Send it on preflight and again with a completed verification. After completion, replace the stored list with the returneddevice_tokens. Keep the old material through a code challenge so a verified re-trust can rotate the same browser record. The platform permits at most ten entries, with a default storage cap of five. Never send both input forms; the singulardevice_token remains supported for existing clients. Keep all device credentials out of browser JSON and logs. Each entry is checked only for the user proving their password, tenant, pool, browser fingerprint and current strength requirement.

Tenant administrators can review the latest invitation, sign-in code and confirmation in Admin’s Email delivery section; platform operators have the equivalent Console view. Status is limited to the configured retention window and current address generation. Delivered means the receiving mail server accepted the message, not that it was read. These are private management views, not additional public sign-in endpoints. A current-address permanent bounce or complaint blocks invitation resends withinvite_delivery_blocked. A committed provisioning result instead carriesinvite.reason: delivery_blocked; preserve the successful account change and show its delivery warning. Correct the address or investigate the complaint before retrying.

Required is checked again before grant issuance, including after policy changes and remembered browser admission. Enrollment preserves the original AMR; a password-only setup does not become MFA. Recovery cannot create browser trust. Preflight always serves v2; explicit unsupported versions are refused. Retired v1 verification endpoints return 410.
Login failures use two explicit wire formats.
Direct POST /api/v1/auth/login/preflight returns RFC 7807 401 code: invalid_credentials, 429 code: rate_limited, or 429 code: login_temporarily_locked. Hosted POST /oauth/login/preflight returns OAuth 400 invalid_grant / error_code: invalid_credentials or 429 temporarily_unavailable with error_code: rate_limited or error_code: login_temporarily_locked. Rate-limited responses include delta-seconds Retry-After; unknown accounts remain indistinguishable from wrong passwords.

OIDC session policy claim

Each newly issued OIDC ID token includes the signed collision-resistant claim https://authreads.com/claims/session_policy. Read its idle_timeout_minutes member after verifying the ID token, then apply that boundary to your relying-party session based on genuine browser activity. Token refresh is server activity and must not extend the human-idle window. At local expiry, start a new authorization request with prompt=login or max_age=0; a plain request may reuse the Authreads session without presenting credentials.

OIDC back-channel logout

In the admin dashboard, register one absolute HTTPS backchannel_logout_uri on the OIDC client. Authreads sends POST application/x-www-form-urlencoded with a single logout_token field when that client's OIDC session is revoked or reaches absolute expiry. Return 200 or 204 after ending the local session; Authreads records that status as an acknowledgement, not proof of remote sign-out. Redirects and other statuses are failures.

Validate the JWT with the discovery document's JWKS: require alg=EdDSA, verify kid, signature, iss, your exact aud, iat, and exp; require the back-channel logout member inevents; reject any nonce; and deduplicate the stable jti. Use sid to end the exact RP session. The token is explicitly typed logout+jwt and also carries sub.

Instant logout requires mutable RP session state. Your receiver must map sid to server-side session or revocation state that every authenticated request consults. A self-contained signed or encrypted browser cookie cannot be invalidated by a server-to-server callback; accepting the logout token alone does not end that browser session. Add a server-side sid store or revocation check. If you remain stateless, do not register a back-channel logout URI; use a short local session lifetime and document that logout is not immediate.