users:view; writes take users:configure.
Creating a user
role(name) orrole_id— resolved server-side;Super_Admincan never be granted through the API.passwordoptional. Given → the seat is login-ready immediately (no forced reset). Omitted → a temporary password is generated; it is returned once astemp_passwordin the response so you can hand it over, and the user must change it at first login.send_welcome— the welcome email (with the temporary password when one was generated) is sent only when this istrue. Default off: an integration that provisions users usually has its own onboarding message.- Honours
Idempotency-Key.
201 with user (the row as GET /v1/users/{id} returns it),
temp_password (only when generated) and welcome_email_sent.
Errors: 409 ALREADY_EXISTS (email already registered), 409 SEAT_LIMIT_REACHED
(the workspace is at its seat allowance — details.hint says how many seats to
buy via POST /v1/subscription/seats; see billing.md),
400 VALIDATION_ERROR with details.fields.
Deactivating and reactivating
PATCH /v1/users/{id} { "status": "inactive" } frees the seat; the user can no
longer sign in. Reactivating ("active") goes through the same seat check as a
create and can answer SEAT_LIMIT_REACHED.
Two guards you cannot turn off: the API never deactivates the last active
Company_Admin of a workspace (409 CONFLICT, details.reason: last_admin),
and never assigns Super_Admin.
Every change writes an auditlog row (api_update) naming the API key that acted.
Parity with the AI assistant
GET /v1/users returns the same id / full_name / email the MCP list_users
tool returns, so an owner id resolved by either can be used by the other.