Skip to main content
This page covers the public tenant auth surface (/auth/*) used by workspace users, tenant admins, and direct API integrations.

The token model

A successful login returns a TokenPair:
string
required
A short-lived JWT (JWT_ACCESS_TTL, default 15 minutes). Send it as Authorization: Bearer <accessToken> on every authenticated request. It embeds tenantId, roleCode, and subjectScope as claims — there is no separate tenant header to set.
string
required
A longer-lived JWT (JWT_REFRESH_TTL, default 30 days) used to obtain a new access token. Browser clients get this automatically as an httpOnly cookie scoped to /api/v1/auth; if you’re integrating server-to-server, read it from the response body instead and store it yourself.
string
required
Access token lifetime, e.g. "15m".
Endpoints marked Public below don’t require a bearer token (they’re how you get one, or they predate having one). Everything else requires Authorization: Bearer <accessToken>.

Register a tenant

string
required
2–80 characters.
string
required
Lowercase, ^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$. This becomes your login slug.
string
required
2–80 characters.
object
Optional structured name (givenName, familyName, nameOrder, phonetic fields for CJK names, preferredDisplayName, nameLocaleRegion) — see the request example.
string
required
Lowercased automatically.
string
required
8+ characters.
string
Initial subject company name.
string
Defaults to free. Public registration only ever accepts free.
string
Required when Turnstile is enabled.
Returns an AuthLoginResult (see me below for the user shape). Disabled in production (PUBLIC_REGISTRATION_ENABLED=false) — use Redeem a code instead. Public.

Redeem a code

Same response shape as register, plus a code field instead of planCode — the plan comes from the code itself.
string
required
8–80 characters.
string
required
string
required
string
required
object
string
required
string
required
string
string
POST /auth/redeem · Public

Log in

string
required
string
required
string
required
string
6-digit TOTP code, if MFA is enrolled.
string
6-digit backup code from /auth/login/mfa/email, used instead of mfaCode when the authenticator is unavailable.
string
Used during first-time MFA enrollment.
string
Two possible response shapes:
AuthLoginResult
{ accessToken, refreshToken, expiresIn, tenant: { id, slug, name }, user } — see session for user.
MfaLoginRequired
{ mfaRequired: true, enrollmentRequired, message, secret?, otpauthUrl?, emailFallbackAvailable? }. If enrollmentRequired is true, this is the account’s first login and it must enroll TOTP before proceeding — see MFA.
POST /auth/login · Public Related:
  • POST /auth/login/resolve — given just an email, a convenience lookup (no password) used by UIs to figure out which tenant(s) an email belongs to before showing the login form.
  • POST /auth/login/mfa/email — re-verifies tenantSlug + email + password, then emails a 6-digit backup code to use as emailCode on /auth/login.
Both are Public.

Refresh and logout

string
Optional — falls back to the alforse_tenant_refresh httpOnly cookie if omitted.
POST /auth/refresh (Public) returns a new TokenPair. POST /auth/logout (requires bearer token) revokes the refresh token and clears the cookie.

Session

AuthUserSummary
{ id, email, name, nameProfile, status, roleCode, subjectScope }
object
{ id, slug, name, edition }
object
Module → permission level map.
object
Resolved plan feature flags.
array
Subject companies visible to this user.
object
{ timezone, reminderLeadDays, reminderHour, reminderEscalationDays, ownerScopeEnabled, preferences }
GET /auth/me is the single call to hydrate a client session after login.
  • PATCH /auth/preferences — language, locale, timezone, currency, calendar/measurement system, first day of week, date/number format. All fields optional.
  • PATCH /auth/profilename and/or a structured nameProfile.

MFA

Tenant admins cannot disable the MFA_REQUIRED_FOR_ADMINS policy for themselves in production — see Configuration.

Passkeys (WebAuthn)

SSO

Invitations and password reset