Authentication endpoints
| Method & path | Body / query | Notes |
|---|---|---|
GET /install/status [public] | — | { installed, logo_url } |
POST /install [public] | company_name, currency_code, locale, time_zone, owner { email, password, display_name } | One-time setup on a fresh self-hosted install; 409 install_already_completed afterwards |
POST /auth/signup [public] | company_name, display_name, email, password, country_code, currency_code?, locale?, time_zone? | 202 { signup_token } and a 6-digit code by e-mail (10-minute token) |
POST /auth/signup/verify [public] | signup_token, otp | 201: creates tenant + owner, signs in; 400 after 3 wrong codes (email_already_registered if taken) |
POST /auth/login [public] | email, password, tenant_slug? | { mfa_required: true, challenge, method, methods, email_hint, attempts_left, resend_in_seconds } or { select_workspace: true, workspaces[] }; throttled. No session until MFA succeeds |
POST /auth/mfa/send-code [public] | challenge | (Re)sends the e-mail code: 1 / 60 s, 5 / hour per user (429 rate_limited) |
POST /auth/mfa/verify [public] | challenge, code | App / e-mail / backup code → { user, permissions, tenant, settings, super_admin, mfa_method, new_device, totp_required }; 400 mfa_code_invalid (details: attempts_left, fallback), 423 mfa_locked, 401 mfa_challenge_expired |
POST /auth/mfa/fallback [public] | challenge, to: email \| backup | Only once the current method is exhausted and the hold elapsed server-side (425 mfa_hold_not_elapsed) |
POST /auth/logout | — | Destroys the session and its device row |
GET /me/security | — | Two-factor status + devices[] (device, ip, location, created, last active, expires, current) |
POST /me/security/totp/setup | — | { otpauth_url, qr_data_url, manual_key } (pending until confirmed) |
POST /me/security/totp/confirm | code | Enables the app; ends the user's other sessions |
POST /me/security/totp/disable | password | Removes the app (403 mfa_totp_required when the workspace requires it, owners excepted) |
POST /me/security/backup-codes | password | { codes[10], generated_at } — shown once, stored hashed; replaces older codes |
DELETE /me/security/devices/:id · POST /me/security/devices/sign-out-others | — | Sign out one device / every other device |
POST /users/:id/mfa/reset [owner] | — | Member back to the e-mail code, signed out everywhere, e-mailed, audited |
GET /auth/me | — | { user (incl. avatar_url), permissions, settings, tenant, super_admin } |
POST /auth/forgot-password [public] | email | Always 202; e-mails a single-use link valid 30 minutes |
POST /auth/reset-password [public] | token, password | Sets the password, ends all sessions |
GET /health [public] | — | Liveness |
Last updated