API Reference
API Reference
GitHub
Admin Panel

User Management

Manage user accounts from the admin panel

Platform administrators create and manage the accounts that can sign in. Every route here is admin-only. Note the split: an account is a person who signs in, and what they may do inside a project is a separate membership row - see Projects .

Create a User

POST /api/v1/admin/users
{
    "email": "user@example.com",
    "password": "secure-password",
    "admin": false
}
FieldNotes
emailRequired. Normalized to lower case.
passwordOptional, minimum 12 characters. Leave it out for an account that signs in only through SSO - it then has no password to guess.
adminPlatform administration. Defaults to false.
adminWhat it grants
falseAn ordinary account. Everything it can do comes from project membership.
truePlatform administration - users, plans, platform settings, scheduled jobs, the whole security log. Also owner-equivalent in any project.

An account created here is a LOCAL account (account_type 1), whether or not you give it a password, and its owner manages their own password, two-factor authentication and passkeys from the profile page. account_type 2 is an account an identity provider owns, and only the provider mints those - those credentials are managed there, not here.

Returns 409 Conflict if the email already exists. Accounts created here are marked email-verified, so they never wait for a confirmation link - that gate is for self-registration.

No project is created here

Nothing is minted for a new account. The user either gets invited to a project or makes one from the projects page, so an install that provisions everyone into a shared project does not collect an empty tenant per employee.

List Users

GET /api/v1/admin/users

Returns every account, oldest first, as {"users": [...]}. The list is not paged - it is bounded by how many people your installation has.

Update a User

PATCH /api/v1/admin/users/{id}
{
    "admin": true,
    "disabled": false,
    "email_verified": true
}

Every field is optional and absent means unchanged. email, password, admin, disabled and email_verified can be set.

Setting disabled to true blocks sign-in. email_verified is the manual release valve for a self-registered account whose confirmation mail never arrived.

You cannot change your own administrator or disabled flags

Self-edits are limited to email and password. The guard exists so the last administrator cannot demote or lock themselves out. Another admin still can.

Reset a User’s Passkeys

DELETE /api/v1/admin/users/{id}/passkeys

Removes every passkey on the account, for the user who lost the device that held the only one. They sign in with their password afterwards and enrol again. The response says how many went:

{
    "removed": 2
}

Not on your own account

Removing a passkey from your own profile asks for your password. This endpoint does not, so allowing it on yourself would let a hijacked admin session strip the phishing-resistant factor off the very account it hijacked. Another admin still can, and the security log records who did.

List a User’s Projects

GET /api/v1/admin/users/{id}/projects

Every project the account is a member of, so you can see what it touches before disabling or deleting it.

Delete a User

DELETE /api/v1/admin/users/{id}

Removes the account immediately and answers 204. Deleting your own account is refused, and an id that names nobody is 404 so a double-click reads as “already gone” rather than silent success.

There is no undo and no grace period

Deletion is immediate. If you want an account kept but locked out, set disabled instead - that is reversible and preserves the audit trail.

Disable 2FA for a User

For the person who lost their authenticator:

DELETE /api/v1/admin/users/{id}/2fa

Refused on your own account. The self-service path in your profile proves possession with a valid code, and this endpoint deliberately does not - allowing it on yourself would turn any hijacked admin session into a 2FA bypass for that admin. Returns 400 if the account has no second factor enrolled. The reset is recorded in the security log.

Revoke All Sessions

Force an account to sign in again everywhere:

POST /api/v1/admin/users/{id}/revoke-sessions

Answers {"revoked": 3}. The node handling the request is consistent immediately and other nodes converge within the session cache TTL. Also recorded in the security log.