Create a user. POST /api/openapi/v1/users, scope admin.v1.user-directory.manage.
- Scope: admin.v1.user-directory.manage
- Permission: Manage users and departments (user-directory)
- Permission type: Manage
- Endpoint: POST/api/openapi/v1/users
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.
If no trusted domain is configured, omit email and use an account, phone number, or employee number. Existing account and password requirements still apply.
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 |
|---|---|---|---|---|---|
| Idempotency-Key | header | string | Required | Idempotency key used to prevent duplicate submissions | "<string>" |
| account | body | string | No | Required when an initial password is provided or organization password login is enabled. | "<string>" |
| department_ids | body | array | null | No | - | ["<string>"] |
| body | string · email | No | "developer@example.com" | ||
| initial_password | body | string · password | No | Required when organization password login is enabled. Providing a password requires a non-empty account. Passwords must contain 8–1024 printable non-space ASCII characters, including uppercase and lowercase English letters and a digit. Special characters are optional. | "<string>" |
| job_number | body | string | No | Employee ID | "<string>" |
| name | body | string | Required | Name | "<string>" |
| phone | body | string | No | Phone number | "<string>" |
| seat_status | body | string | No | Seat assignment | "unassigned" |
Request example
cURL
Responses
201 Created
| 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>" |