Sign a manager in
POST
/api/v1/auth/login
Exchanges an email or username and a password for a tenant-scoped session token. The tenant is taken from the host when you call a tenant subdomain, and a selector in the body is discarded in that case.
mfa_required is a 401 with the same code as a wrong password. Branch on details.reason, never on the status or the message: six different login outcomes share ERR_UNAUTHORIZED and only the reason tells them apart. expires_at is unix SECONDS, not milliseconds and not a formatted timestamp.
At a glance
- Authentication
- Public
- Rate limit
login
Parameters
| Parameter | Description |
|---|---|
emailrequired
body · string
|
Email or username. |
passwordrequired
body · string
|
The manager's password. |
totp_code
body · string
|
Six-digit code or a recovery code. Sent on the second attempt, after the first returns mfa_required. |
tenant_slug
body · string
|
Honoured only when the host carries no tenant. Ignored outright on a tenant subdomain. |
refresh
body · boolean
|
Opt in to the refresh-token flow. Omitting it returns one long-lived token and no refresh fields at all. |
Errors
| Code | When it is returned |
|---|---|
ERR_VALIDATION400
|
the host carries no tenant and no selector was supplied — details.reason tenant_required |
ERR_UNAUTHORIZED401
|
wrong credentials (invalid_credentials), two-factor needed (mfa_required), or a bad code (mfa_invalid) |
ERR_RATE_LIMITED429
|
too many consecutive failures on this account — details.reason login_locked |
ERR_UNAVAILABLE503
|
the tenant's portal has been switched off — details.reason site_offline |