I IntelliAuth Docs

/api/v1/users/* is the admin user surface. It is called by trusted backends — your management UIs, your batch jobs, your migration scripts. Scoped to users:read (reads) and users:write (mutations).

End-user self-service does NOT happen here; that's the Me API.

List users

http
GET /api/v1/users
Authorization: Bearer <access-token>
Required scope: users:read

Query parameters:
  cursor       — opaque pagination cursor
  limit        — page size (1–250, default 50)
  email        — exact email filter
  state        — 'active' | 'disabled' | 'pending'
  created_after — ISO timestamp
  q            — free-text search across email + name + attributes
json
{
  "data": [
    {
      "id": "usr_01HZX...",
      "email": "user@cymmetri.com",
      "email_verified": true,
      "name": "User Name",
      "state": "active",
      "created_at": "2026-01-15T10:00:00Z",
      "last_signed_in_at": "2026-05-17T08:00:00Z"
    }
  ],
  "meta": { "next_cursor": "...", "limit": 50 }
}

Create a user

http
POST /api/v1/users
Authorization: Bearer <access-token>
Content-Type: application/json
Required scope: users:write
Idempotency-Key: <uuid>     (recommended)

{
  "email": "finance.lead@cymmetri.com",
  "name": "Finance Lead",
  "password": "a temporary one",
  "password_must_be_reset": true,
  "email_verified": false,
  "attributes": { "department": "finance" }
}

Returns the created user. If email_verified is omitted or false, a verification email is sent.

If the email already exists, returns 409 user_exists. If you want "create or get", call GET /api/v1/users?email=... first.

Look up a user

http
GET /api/v1/users/{user_id}
Authorization: Bearer <access-token>
Required scope: users:read

The detailed user record includes:

json
{
  "data": {
    "id": "usr_01HZX...",
    "email": "user@cymmetri.com",
    "email_verified": true,
    "name": "User Name",
    "state": "active",
    "attributes": { ... },
    "mfa_factors": [
      { "kind": "webauthn", "count": 2 },
      { "kind": "totp", "count": 1 }
    ],
    "groups": [
      { "id": "grp_01HZX...", "name": "Finance" }
    ],
    "applications_used": [ "app_01HZX...", "app_01HZY..." ],
    "created_at": "...",
    "updated_at": "...",
    "last_signed_in_at": "..."
  }
}

The DTO summarises sub-resources (factor counts, group memberships, recently-used applications) so a single fetch is enough for a typical admin "user detail" page. Fetch the full lists with the per-sub-resource endpoints when needed.

Update a user

http
PATCH /api/v1/users/{user_id}
Authorization: Bearer <access-token>
Content-Type: application/json
Required scope: users:write

{
  "name": "Anita Singh",
  "attributes": { "department": "engineering" }
}

Fields not in the body are unchanged. Some fields are immutable (id, created_at); the API rejects an attempt to PATCH them.

Disable / enable

Soft state changes that preserve the record:

http
POST /api/v1/users/{user_id}/disable
POST /api/v1/users/{user_id}/enable
Required scope: users:write

A disabled user cannot sign in. All their sessions are revoked. Their record stays. Re-enabling restores the ability to sign in but does not restore sessions.

Delete a user

http
DELETE /api/v1/users/{user_id}
Authorization: Bearer <access-token>
Required scope: users:write

Hard delete: the user record + all their factors + all their sessions are removed. The audit log entries about them are retained per the tenant's retention policy.

For GDPR-style erasure where you want absolute removal including audit, the data export + erasure flow is in the tenant admin console.

Reset password (admin-initiated)

http
POST /api/v1/users/{user_id}/reset-password
Authorization: Bearer <access-token>
Required scope: users:write

Sends the user a password-reset email. Does not return a new password.

To set a temporary password directly (operator-set rather than user-set), use PATCH with { "password": "...", "password_must_be_reset": true }. The user is forced to change it on next sign-in.

Force MFA reset

http
POST /api/v1/users/{user_id}/force-mfa-reset
Authorization: Bearer <access-token>
Required scope: users:write

Removes all the user's MFA factors. They are forced to re-enrol on next sign-in. Recovery path for users who lost their second factor; pair with a separate user-identity-verification step.

Bulk import

http
POST /api/v1/users/bulk-import
Authorization: Bearer <access-token>
Content-Type: application/x-ndjson
Required scope: users:write

{"email":"a@cymmetri.com","name":"A","password":"..."}
{"email":"b@cymmetri.com","name":"B","password":"..."}

Streamed input. Returns a job id; poll the job for status:

http
GET /api/v1/users/bulk-import/{job_id}
json
{
  "data": {
    "id": "job_01HZX...",
    "state": "running",
    "imported": 1500,
    "failed": 3,
    "errors": [ ... ]
  }
}

For tens-of-thousands-of-users migrations, the bulk-import endpoint is preferable to a serial loop over POST /api/v1/users — it batches transactionally on the platform side.

Common errors

Error

When

user_not_found

The id doesn't exist or you can't see it (404)

user_exists

A user with that email already exists on create

insufficient_scope

Token doesn't carry the capability this action requires

password_policy_violation

The password does not meet the tenant's policy

email_invalid

The email is malformed

See also