Users and admin API
These endpoints require the caller to have the global admin:* scope (or a session belonging to a user with is_admin=true). They control identity (users, password resets) and configuration (effective settings, version check, first-boot setup).
User scopes inside a project are still managed through memberships; this page is for the parallel surface of global user state that lives outside of any single project.
Base path: /api/v1/users. All routes require global admin.
List users
Section titled “List users”GET /api/v1/usersReturns a list of UserPublic:
[ { "id": "...", "email": "alice@example.com", "first_name": "Alice", "last_name": "Doe", "display_name": "Alice", "is_admin": true, "is_active": true, "timezone": "UTC", "created_at": "...", "updated_at": "...", "last_login_at": "..." }]Get user
Section titled “Get user”GET /api/v1/users/{user_id}Create user
Section titled “Create user”POST /api/v1/usersCSRF-protected.
{ "email": "alice@example.com", "first_name": "Alice", "last_name": "Doe", "display_name": "Alice", "password": "min-8-chars", "is_admin": false, "timezone": "UTC"}Password is 8..256 chars, hashed with argon2id. The created user has no project memberships; add them through the memberships endpoint or by inviting them into a specific project.
Update user
Section titled “Update user”PATCH /api/v1/users/{user_id}CSRF-protected. Any subset of:
{ "first_name": "...", "last_name": "...", "display_name": "...", "is_admin": true, "is_active": false, "timezone": "America/New_York"}Cannot change email (rename requires creating a new user and migrating memberships). Cannot demote the last is_admin=true user (the brain enforces a last-admin protection at the global level mirroring the per-project rule).
Reset password
Section titled “Reset password”POST /api/v1/users/{user_id}/passwordCSRF-protected.
{"password": "new-password-min-8-chars"}Resets the user’s password without requiring them to know the old one. Use sparingly; the user’s existing sessions are invalidated immediately. The action writes a user.password_reset_by_admin audit row attributed to the caller.
Delete user
Section titled “Delete user”DELETE /api/v1/users/{user_id}CSRF-protected. Soft-delete (sets is_active=false); the row remains for audit traceability. Cannot delete the last is_admin=true user.
Admin: system + settings
Section titled “Admin: system + settings”These routes back the dashboard’s Settings, Admin pages. Caller must be is_admin=true.
Effective settings snapshot
Section titled “Effective settings snapshot”GET /api/v1/admin/settingsReturns the resolved Settings dict (post-env-var, post-defaults, post-.env). Secrets are masked. Useful for debugging “is this env var actually picked up?” without giving the admin shell access. Mirrors z4j config show on the CLI.
Versions snapshot
Section titled “Versions snapshot”GET /api/v1/admin/system/versionsReturns the brain’s installed package versions for z4j and every adapter, plus the dashboard build’s commit hash if shipped that way. Used by the dashboard’s “About” page.
Check for updates
Section titled “Check for updates”POST /api/v1/admin/system/versions/checkFetches the upstream version manifest (Z4J_VERSION_CHECK_URL, default points at the public repo) and returns a list of packages with newer releases available. The check is read-only; nothing is installed. Cached server-side so multiple admins clicking the button don’t hammer the upstream URL.
First-boot setup
Section titled “First-boot setup”The setup endpoints are active only when the brain has no admin user. Once any admin exists, they return 409 setup_already_complete.
GET /api/v1/setup/status # is setup needed?POST /api/v1/setup/complete # mint the first admin using a one-shot tokenThe setup form is also served at GET /setup as HTML for evaluators booting a brain locally.
Token TTL is Z4J_FIRST_BOOT_TOKEN_TTL_SECONDS (default 15 minutes). Verification attempts are bounded by Z4J_FIRST_BOOT_ATTEMPTS_PER_IP (default 30 per 15-minute sliding window) so a leaked URL cannot be brute-forced.
For deployments that prefer to skip the form entirely, set Z4J_BOOTSTRAP_ADMIN_EMAIL and Z4J_BOOTSTRAP_ADMIN_PASSWORD; the brain creates the admin at boot and the setup endpoints stay locked from the start. See first-admin.