Skip to main content
Everything a headless integration needs to manage the people in a workspace: who exists (to assign work), add a colleague, deactivate one, change a role. Reads take users:view; writes take users:configure.

Creating a user

  • role (name) or role_id — resolved server-side; Super_Admin can never be granted through the API.
  • password optional. Given → the seat is login-ready immediately (no forced reset). Omitted → a temporary password is generated; it is returned once as temp_password in 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 is true. Default off: an integration that provisions users usually has its own onboarding message.
  • Honours Idempotency-Key.
Response: 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.