---
title: "Create a new user (SystemAdmin)"
method: POST
path: "/system/admin/users/create"
tags: ["System Admin"]
---

# Create a new user (SystemAdmin)

`POST /system/admin/users/create`

Provision a new local user account (SystemAdmin only).
When `password` is omitted or null, a cryptographically random
password is generated (OIDC-style crypto/rand + base64url)
and returned once in the response body. Any provided value,
including empty string, is policy-checked. Tenant provisioning
follows the shared auth.default_tenant_mode policy.

## Request body

- GithubComTencentWeKnoraInternalTypesAdminCreateUserRequest
  - `email` string, required
  - `password` string
  - `username` string, required

## Response `200`

Identity already exists, returns the existing user

- InternalHandlerCreateSystemUserResponse
  - `generated_password` string — GeneratedPassword is the plaintext password when the server auto-generated one. Absent when the caller supplied the password.
  - `user` GithubComTencentWeKnoraInternalTypesUserInfo
    - `avatar` string
    - `can_access_all_tenants` boolean
    - `created_at` string
    - `email` string
    - `id` string
    - `is_active` boolean
    - `is_system_admin` boolean
    - `preferences` GithubComTencentWeKnoraInternalTypesUserPreferences
      - `last_active_tenant_id` integer — LastActiveTenantID remembers the last workspace the user actively switched into, so a fresh login (new device, cleared browser, new refresh token) lands them back in that workspace instead of always bouncing to their home workspace. Written by the SPA's preferences PUT and by service-level SwitchTenant (including when switching home, which stores the home ID). Login / RefreshToken validate that the workspace still exists and the user still has an active membership (or CanAccessAllTenants) before honouring this preference; an invalid pointer is best-effort cleared and the user falls back to home. Refresh JWT claims have no tenant_id, so RefreshToken re-resolves from this field. nil = no preference (use user.TenantID, i.e. home) *0 = "clear preference" sentinel for the partial-update endpoint (UpdateUserPreferences turns this into nil). Otherwise treat a stored *0 the same as nil. *N = preferred workspace id.
      - `oidc_only_login` boolean — OidcOnlyLogin is set server-side when an account is auto-provisioned via OIDC with a random password the user never received. The profile UI hides self-service password rotation until the user sets a known password via ChangePassword (which clears this flag).
    - `tenant_id` integer
    - `updated_at` string
    - `username` string

## Other responses

- `201` — User created successfully
- `400` — Invalid request or weak password
- `403` — Forbidden: not a system admin
- `409` — Email and username refer to conflicting identities
- `500` — Internal error

## Changes

- **2026-08-25** `8f184d39c6b7` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/tencentblueking/apis/weknora-api/changes/system/admin/users/create/post.md)

---

[API](https://skmtc.dev/tencentblueking/apis/weknora-api.md) · [All operations](https://skmtc.dev/tencentblueking/apis/weknora-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/tencentblueking/weknora-api/revisions/c70887fb1bf7/schema)
