Authentication API¶
Endpoints for user authentication, registration, profile management, SSO, one-click demo login, and account deletion.
All endpoints in this section use the /api/auth/ prefix. login, register, registration-status, activate, password/forget, password/set, accept/invitation, accept/password, and the sso/* endpoints do not require an authentication token; all others do.
Several endpoints are rate-limited per client IP — see the API Overview for the current limits.
Login¶
Request body:
Response:
An unknown email and a wrong password both return 401 with {"error": "Invalid email or password"}, so the endpoint does not reveal which emails have an account. On a host with DEMO_ONLY_LOGIN=true it returns 403 with {"error": "demo_only"}.
Registration Status¶
Public flags the login page reads at mount time. Safe to call anonymously.
Response:
| Field | Meaning |
|---|---|
registration_enabled |
The "Create account" prompt is shown. |
demo_available |
A seeded read-only demo user exists, so "Try the live demo" is shown. |
demo_only |
DEMO_ONLY_LOGIN=true: the login page shows only the demo button. |
Controlled by the REGISTRATION_ENABLED env var. Left unset, it is true until the first organisation exists and false afterwards — see Configuration Reference.
Register¶
Request body:
{
"user": {
"email": "user@example.com",
"password": "password",
"password_confirmation": "password",
"first_name": "John",
"last_name": "Doe",
"phone": "+1000000000"
},
"organisation": {
"name": "My Org",
"website": "https://example.com"
}
}
Creates a new organisation with the caller as its first admin. Sends an activation email.
When registration is disabled:
If registration is closed — REGISTRATION_ENABLED=False, or left unset on an instance that already has an organisation — this endpoint returns 403 Forbidden:
{
"status": "error",
"error": "registration_disabled",
"message": "This SerOps instance does not accept new registrations. Ask an admin for an invite, or self-host your own instance: https://serops.ai/docs/getting-started/quick-start-self-hosted/"
}
Get Profile¶
Returns the authenticated user's profile information. The login response's user has the same fields.
| Field | Meaning |
|---|---|
role |
viewer, user or admin in the user's organisation. |
is_staff |
Platform staff (read-only). |
permissions |
Every permission the user holds, sorted, e.g. ["batch.read", "issue.read", "org.read", …]. See Team Management for the list. Clients should show or hide actions from this list rather than from role. |
Upload Avatar¶
Uploads a profile avatar image for the authenticated user.
Update Password¶
Request body:
{
"old_password": "current",
"new_password": "new-secure-password",
"new_password_copy": "new-secure-password"
}
Forgot Password¶
Request body:
Sends a password reset email to the specified address.
Set Password (Reset)¶
Request body:
Completes the password reset flow using the link from the reset email.
Resend Verification Email¶
Resends the account activation email for the authenticated user.
Activate Account¶
Activates the user account using the token from the verification email. This is a GET because the activation link is opened directly from an email.
Accept Invitation¶
Accepts a team invitation using the token from the invitation email. Associates the user with the inviting organisation. This is a GET because the invitation link is opened directly from an email.
Set Password (Invitation)¶
Request body:
Sets the password for a user who joined via team invitation.
Logout¶
Invalidates the current authentication token.
Delete Account (GDPR Right to Erasure)¶
Permanently deletes the authenticated user's account and their personal profile data (name, avatar, phone). Team memberships are removed and any chat sessions owned by the user are deleted. Batches, issues, and other organisation-scoped data are retained under the organisation's control.
If the user is the sole admin of an organisation, the request is rejected — transfer admin to another member first, or delete the organisation via /api/organisation/delete/{id}/.
Response: 204 No Content.
SSO Configuration¶
Returns the organisation's OpenID Connect settings (sso_enabled, sso_provider — oidc or none, sso_client_id, sso_discovery_url, sso_client_secret_configured) and sso_redirect_uri, the URL to register at the identity provider. PUT (admin only) updates them; the client secret is write-only. SAML is not supported.
SSO Login Init¶
Request body:
Looks up the organisation that owns the email and returns {"auth_url": "..."}, the identity provider's sign-in page. Every case without an auth URL — unknown email, SSO switched off, inactive or demo account — returns the same 400 {"error": "SSO is not available for this account."}, so the endpoint does not reveal who has an account. 502 means the identity provider's discovery URL could not be reached.
SSO Callback¶
The identity provider redirects the browser here. SerOps exchanges the code, reads the user's email from the userinfo endpoint and signs them in:
- An existing user signs in only if they belong to the organisation that started the flow and are active.
- An unknown email becomes a new
viewerin that organisation, with no password. - An email the provider marks
email_verified: falseis refused.
On success it sets a short-lived HttpOnly handoff cookie and redirects to the frontend's /auth/callback, which calls sso/exchange to swap the cookie for a Knox token. On any failure it redirects to /login?sso=failed.
SSO Token Exchange¶
Exchanges the short-lived HttpOnly handoff cookie set by sso/callback for a usable Knox token + user payload. The browser sends the handoff cookie automatically; the caller must use withCredentials: true.
Response:
This two-step flow keeps the SSO token out of the URL and out of local storage until after exchange, closing the risk of tokens leaking via referer headers or browser history.
Related¶
- API Overview -- Base URL, response format, rate limits, and error codes
- Settings & Admin -- Organisation-level security settings
- Configuration Reference --
REGISTRATION_ENABLEDand other access flags