Update a user. PATCH /api/openapi/v1/users/{userId}, scope admin.v1.user-directory.manage.
- Scope: admin.v1.user-directory.manage
- Permission: Manage users and departments (user-directory)
- Permission type: Manage
- Endpoint: PATCH/api/openapi/v1/users/{userId}
Trusted email domain validation
A non-empty email must exactly match a currently verified, non-deleted domain in the organization. With no trusted domains, the request fails with 422 directory_user_email_domain_not_verified. Wildcards and parent-domain inheritance are not supported.
Validation uses the complete profile after applying the patch. Omitting email preserves its current value, so changing only the name or departments can still fail. To clear email, explicitly send "email": "" and retain at least one other valid identity.
This tightens the previous behavior for organizations without trusted domains. Before upgrading, callers must configure and verify a matching domain or remove email as described above. Independent account enablement, seat assignment, and existing sign-in sessions retain their previous rules.
Authentication and request headers
Call with an application API key. This endpoint checks only the scope above; read, manage and execute permissions do not imply one another.
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
| Authorization | header | string | Yes | Application API key, passed as a Bearer token. | Bearer qwk_*** |
| X-Request-Id | header | string | No | Optional request tracing identifier; generated by the server if omitted. | req-20260831-001 |
Request parameters
| Name | Location | Type | Required | Description | Example |
|---|---|---|---|---|---|
| userId | path | string · uuid | Required | User ID | "<uuid>" |
| Idempotency-Key | header | string | No | Idempotency key used to prevent duplicate submissions | "<string>" |
| account | body | string | No | Account | "<string>" |
| department_ids | body | array | null | No | - | ["<string>"] |
| body | string | No | "<string>" | ||
| job_number | body | string | No | Employee ID | "<string>" |
| name | body | string | No | Name | "<string>" |
| phone | body | string | No | Phone number | "<string>" |
Request example
cURL
Responses
200 OK
| Name | Type | Required | Description | Example |
|---|---|---|---|---|
| account | string | No | Account | "<string>" |
| department_ids | array | null | Yes | Departments (department IDs) | ["<string>"] |
| string | No | "<string>" | ||
| job_number | string | No | Employee ID | "<string>" |
| name | string | Yes | Name | "<string>" |
| phone | string | No | Phone number | "<string>" |
| qid | string · uuid | Yes | QID | "<uuid>" |
| seat_status | string | Yes | Seat assignment | "assigned" |
| source | string | Yes | Source | "manual" |
| status | string | Yes | User status | "pending" |
| updated_at | string · date-time | Yes | Updated at | "2026-08-27T10:00:00Z" |
| third_party_user_id | string | Yes | External user ID; an empty string when unset. | "external-001" |
| departments | array | Yes | Department details; an empty array when no departments are assigned. | [{"id":"22222222-2222-4222-8222-222222222222","name":"Engineering","path":"Company/Engineering","external_id":"external-dept","is_primary":true}] |
| credential | object | Yes | Password lifecycle metadata; contains no password or hash. | {"password_state":"active","must_change_password":false,"credential_version":2} |
| created_at | string · date-time | Yes | User creation time. | "2026-09-19T01:00:00Z" |
| last_active_at | string · date-time | No | Latest IAM activity time; omitted when unavailable. This is not the latest business activity time. | "2026-09-23T01:00:00Z" |
| departments[].id | string · uuid | Yes | Department ID. | - |
| departments[].name | string | Yes | Department name. | - |
| departments[].path | string | Yes | Department path. | - |
| departments[].external_id | string | No | External department ID; omitted when unset. | - |
| departments[].is_primary | boolean | Yes | Whether this is the primary department. | - |
| credential.password_state | string | Yes | Password state: unset (not set), initial (initial password), or active (active password). | - |
| credential.must_change_password | boolean | Yes | Whether a password change is required. | - |
| credential.credential_version | integer | Yes | Credential version. | - |
| credential.password_updated_at | string · date-time | No | Password update time; omitted when unavailable. | - |
| credential.first_login_completed_at | string · date-time | No | First completed sign-in time; omitted before completion. | - |
default Flat business error
| Name | Type | Required | Description | Example |
|---|---|---|---|---|
| code | string | No | Stable business error code | "<string>" |
| detail | string | Yes | Human-readable error description | "<string>" |
| details | OpenapiErrorDetails | No | Error details | {"field":"<string>","reason":"<string>","suggestion":"<string>"} |
| details.field | string | No | Request field that failed validation | "<string>" |
| details.reason | string | No | Stable validation failure reason | "<string>" |
| details.suggestion | string | No | Suggested normalized value | "<string>" |
| error | string | Yes | Stable HTTP error type | "<string>" |