Auth API
Authenticate users and manage sessions and access tokens.
Generated from the Celerp 2.4.0 OpenAPI schema, 16 September 2026.
POST /auth/api-key
Create Api Key
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
Example
curl -X POST http://localhost:8000/auth/api-key \
-H "Authorization: Bearer $TOKEN"GET /auth/bootstrap-status
Bootstrap Status
Public endpoint: returns whether the system has been bootstrapped. UI uses this to decide whether to show the first-admin registration wizard (bootstrapped=false) or the normal login screen (bootstrapped=true). Once any user exists, registration is locked out from the public UI.
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
Example
curl -X GET http://localhost:8000/auth/bootstrap-status \
-H "Authorization: Bearer $TOKEN"POST /auth/change-password
Change Password
Change password for the currently authenticated user.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
current_password | string | yes | Current Password |
new_password | string | yes | New Password |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/change-password \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/login
Login
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | |
password | string | yes | Password |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/login \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/login-force
Login Force
Like /login but evicts all other active sessions from the tracker first.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | |
password | string | yes | Password |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/login-force \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/logout
Logout
Revoke the caller's session, then rotate their nonce so every existing access AND refresh token for this user is immediately rejected. Accepts EITHER a current access token (Authorization header) or a current v2 refresh token (JSON body), so a browser whose access cookie has expired but whose refresh cookie is still live can still log out server-side (F3). Revocation only happens after the presented credential's snonce is confirmed current under the ``UserAuthState`` row lock: a stale credential cannot rotate a newer session generation, and logout stays idempotent (always 200).
Request body
LogoutRequest, optional
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/logout \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'GET /auth/my-companies
My Companies
List all companies the current user has access to.
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
Example
curl -X GET http://localhost:8000/auth/my-companies \
-H "Authorization: Bearer $TOKEN"POST /auth/password-reset/confirm
Password Reset Confirm
Confirm password reset with token and new password.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | Token |
new_password | string | yes | New Password |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/password-reset/confirm \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/password-reset/request
Password Reset Request
Request a password reset link. Always returns 200 (prevents user enumeration).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/password-reset/request \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/register
Register
Register first admin. Locked out after bootstrap (any user exists). A transaction-scoped advisory lock serializes concurrent first-admin registrations so exactly one wins: the second caller blocks until the first transaction finishes, then re-checks whether an owner exists. Core bootstrap rows and direct seed data commit once through the central token issuer, so those changes are all-or-nothing. Module lifecycle hooks retain their existing best-effort policy; the one-time setup code is consumed only after commit.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
company_name | string | yes | Company Name |
email | string | yes | |
name | string | yes | Name |
password | string | yes | Password |
setup_code | string, optional | -- | Setup Code |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/register \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'POST /auth/switch-company/{company_id}
Switch Company
Switch the active company. Returns a new JWT scoped to the target company. Only succeeds if the user has an active entry in user_companies for that company.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
company_id | path | yes | string | -- |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/switch-company/:company_id \
-H "Authorization: Bearer $TOKEN"POST /auth/token/refresh
Refresh Token
Exchange a valid refresh token for a new access token + rotated refresh token. Fully DB-authoritative: the refresh token is decoded strictly (v2, type, non-empty snonce), then re-bound to current DB state - active user, active membership, company-validity rule, and exact nonce equality. The new pair's role and email come from current DB membership, never from the refresh JWT. Every failure mode returns the same neutral "Invalid refresh token" so the caller learns nothing about which element failed.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
refresh_token | string | yes | Refresh Token |
Responses
| Status | Description | Body |
|---|---|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
Example
curl -X POST http://localhost:8000/auth/token/refresh \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'