Users API
Accounts are managed under /api/db-devops/users, invitations under /api/onboarding, and passwords set from a link under /api/auth. Changes need the admin role. Errors are JSON with error and code.
Routes
| Method | Endpoint | Who | Purpose |
|---|---|---|---|
| GET | /api/db-devops/users | Anyone signed in | Admins get every account; others get only their own |
| GET | /api/db-devops/users/:id | Anyone signed in | One account; another account is 404 to a non-admin |
| POST | /api/db-devops/users | Admin | Create an account with a password |
| PUT | /api/db-devops/users/:id | Admin | Change name, email or role |
| PUT | /api/db-devops/users/:id/password | Admin, or the account itself | Set a new password |
| POST | /api/db-devops/users/:id/deactivate, /activate | Admin | Stop or allow sign-in |
| DELETE | /api/db-devops/users/:id | Admin | Delete an account |
| POST | /api/onboarding/provision-user | Admin | Invite: create the account and a setup link |
| POST | /api/onboarding/resend-invite | Admin | New setup link for an invite that is still pending (reactivates a deactivated invite) |
| POST | /api/auth/reset-password | Holder of a setup or reset link | Set the password from the link's token |
| GET | /api/auth/password-policy | Anyone | { "minLength", "complexity", "rule" }: the rule every new password must meet |
| GET | /api/auth/idp/status | Anyone | The providers turned on, and passwordSignIn: everyone, or administrators when local authentication is off |
/api/auth/register, GET /api/auth/users, PUT /api/auth/users/:id/role and DELETE /api/auth/users/:id (which deactivates) apply the same checks.
Accounts
{ "id": "…", "email": "dba@example.com", "name": "Dana", "role": "approver", "is_active": true,
"last_login": "2026-10-08T14:02:11Z", "invite_pending": false, "created_at": "…", "updated_at": "…" }
invite_pending is true for an invited account that has not set its password yet. No route returns passwords, password hashes, MFA secrets, backup codes or reset tokens.
Creating and changing accounts
POST /api/db-devops/users
{ "email": "dba@example.com", "name": "Dana", "role": "approver", "password": "Strong-pass-2026!" }
PUT /api/db-devops/users/:id
{ "role": "release_manager" }
PUT /api/db-devops/users/:id/password
{ "new_password": "Another-pass-2026!", "current_password": "…" }
POST /api/onboarding/provision-user
{ "email": "dba@example.com", "name": "Dana", "role": "user", "notify": true }
→ 201 { "success": true, "user": { … }, "setupUrl": "https://…/setup?token=…", "emailed": true }
roleisadmin,release_manager,approveroruser(defaultuser); anything else is refused, never replaced.emailmust be a valid address of up to 254 characters;nameup to 255 characters.- Passwords need at least 12 characters, with an uppercase and a lowercase letter, a digit and a symbol.
current_passwordis required when you change your own password. - Only
name,emailandrolecan be sent toPUT /users/:id.
Sessions
Every request checks the account behind the session token. A deactivated or deleted account, or a session issued before a password reset, gets 401:
{ "error": "Your session has ended because the account was deactivated. Sign in again.", "code": "SESSION_ENDED" }
A role change applies to the account's next request.
Error codes
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_USER | An email, name or role is missing or invalid, or a field cannot be changed; the message names it |
| 400 | WEAK_PASSWORD | The password does not meet the rule; the message states it |
| 401 | SESSION_ENDED | The account was deactivated or deleted, its password was reset, or it no longer holds a license seat |
| 403 | CURRENT_PASSWORD_WRONG | Changing your own password without your current one |
| 404 | USER_NOT_FOUND | No such account, a malformed id, or another account read by a non-admin |
| 409 | EMAIL_TAKEN | Another account has that email |
| 409 | LAST_ADMIN | The change would leave no active admin |
| 409 | OWN_ACCOUNT | Deactivating or deleting your own account |
| 409 | USER_IN_USE | The account is still referred to by records that must be kept; deactivate it instead |
| 409 | NO_FREE_SEAT | Creating, inviting or reactivating a user when every license seat is taken |
| 500 | USER_CHANGE_FAILED, USERS_UNREADABLE, INVITE_FAILED | The change, the read or the invitation failed; the server log has the cause |