6. Tenant Users and Roles
6.1 Tenant Users
Endpoint Summary
| Path | Summary | Method |
|---|---|---|
/api/v1/tenants/{tenant_id}/users |
List tenant users | GET |
/api/v1/tenants/{tenant_id}/users |
Create tenant user | POST |
/api/v1/tenants/{tenant_id}/users/{user_id} |
Get tenant user | GET |
/api/v1/tenants/{tenant_id}/users/{user_id} |
Update tenant user | PATCH |
/api/v1/tenants/{tenant_id}/users/{user_id} |
Delete tenant user | DELETE |
GET /api/v1/tenants/{tenant_id}/users
List tenant users
Return all users that belong to the specified tenant. The response includes a total count field. Tenant Admins can only list users within their own tenant.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Tenant users retrieved successfully. | UserListResponse |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 422 | Validation Error | HTTPValidationError |
| 500 | Internal server error. | - |
Response Body (200, UserListResponse)
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
total |
integer | yes | n/a | 0, 5, 50 |
Total count of Tenant Users in this response. |
users |
array of User object |
no | n/a | Array of Tenant User objects. Empty array if no users found. |
Example
{
"total" : 1,
"users" : [
{
"auth_settings" : {
"auth_mode" : "local"
},
"created_at" : "2026-01-01T00:00:00Z",
"display_name" : "Alice Anderson",
"email" : "alice@fintech.example.com",
"id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"updated_at" : "2026-01-01T00:00:00Z",
"username" : "alice"
}
]
}POST /api/v1/tenants/{tenant_id}/users
Create tenant user
Create a new tenant user within the specified tenant. The name must be unique within the tenant. The password is hashed server-side; the plaintext value is never stored.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
Request Body (application/json, required)
Schema: UserCreateRequest
Request payload for creating a Tenant User.
The password is hashed server-side before storage; the plaintext value is never persisted. The name must be unique within the tenant.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
auth_settings |
LocalAuthSettings object or PamAuthSettings object |
yes | n/a | {"auth_mode":"local"}, {"auth_mode":"pam","service":"login"} |
Authentication backend for this user, discriminated on auth_mode. |
display_name |
string, nullable | no | null |
Alice Anderson |
Human-readable full name. Optional; username remains the unique handle. |
email |
string, nullable | no | null |
alice@fintech.example.com |
Optional contact email for the Tenant User. |
password |
string (password) | yes | n/a | Tenant User password (min 8 characters). Hashed server-side before storage. | |
username |
string | yes | n/a | alice |
Tenant User username. Must be unique within the tenant. Whitespace, control and invisible characters are not allowed. |
Example
{
"auth_settings" : {
"auth_mode" : "local"
},
"display_name" : "Alice Anderson",
"email" : "alice@fintech.example.com",
"password" : "secure-password",
"username" : "alice"
}Responses
| Status | Description | Schema |
|---|---|---|
| 201 | Tenant user created successfully. | UserCreateResponse |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 409 | Conflict. A user with this username already exists in the target tenant. | - |
| 422 | Validation error. | - |
| 500 | Internal server error. | - |
Response Body (201, UserCreateResponse)
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
id |
string (uuid) | yes | n/a | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
Unique Tenant User identifier (UUID) assigned by the system. |
Example
{
"id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}GET /api/v1/tenants/{tenant_id}/users/{user_id}
Get tenant user
Retrieve a specific tenant user by ID. Returns 404 if the user does not exist or belongs to a different tenant.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
user_id |
path | string (uuid) | yes | Tenant user identifier (UUID). |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Tenant user retrieved successfully. | GetUserResponse |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 404 | Tenant user not found. | - |
| 422 | Validation Error | HTTPValidationError |
| 500 | Internal server error. | - |
Response Body (200, GetUserResponse)
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
user |
User object |
yes | n/a | Tenant User entity with all available details. |
Example
{
"user" : {
"auth_settings" : {
"auth_mode" : "local"
},
"created_at" : "2026-01-01T00:00:00Z",
"display_name" : "Alice Anderson",
"email" : "alice@fintech.example.com",
"id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"updated_at" : "2026-01-01T00:00:00Z",
"username" : "alice"
}
}PATCH /api/v1/tenants/{tenant_id}/users/{user_id}
Update tenant user
Apply a partial update to the specified tenant user: set a new password, change the authentication backend (auth_settings), update the email and/or the display_name. At least one field must be supplied. This is an administrative operation - the caller does not need to supply the current password. Returns 400 if a password change is requested for a user whose resulting auth mode is not local. Returns 404 if the user does not exist or belongs to a different tenant.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
user_id |
path | string (uuid) | yes | Tenant user identifier (UUID). |
Request Body (application/json, required)
Schema: UserPatchRequest
Request payload for updating a Tenant User.
Allows partial updates of new_password, auth_settings, email and/or display_name; at least one must be supplied. Administrative operation - the caller does not need to supply the current password. Intended for Tenant Admin or Platform Admin use only.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
auth_settings |
LocalAuthSettings object or PamAuthSettings object, nullable |
no | null |
{"auth_mode":"local"}, {"auth_mode":"pam","service":"login"} |
Updated authentication backend for this user, discriminated on auth_mode. |
display_name |
string, nullable | no | null |
Alice Anderson |
Updated human-readable full name for the Tenant User. |
email |
string, nullable | no | null |
alice@fintech.example.com |
Updated contact email for the Tenant User. |
new_password |
string (password), nullable | no | null |
New password for the Tenant User (min 8 characters). Hashed server-side before storage. |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | Password updated successfully. | - |
| 400 | Bad request. A password change was requested for a user whose auth mode is not ‘local’. | - |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 404 | Tenant user not found. | - |
| 422 | Validation error. Password does not meet minimum length requirement. | - |
| 500 | Internal server error. | - |
DELETE /api/v1/tenants/{tenant_id}/users/{user_id}
Delete tenant user
Permanently delete a tenant user by ID, together with everything that would still authenticate as it: the API tokens it holds and its role bindings. Returns 404 if the user does not exist or belongs to a different tenant. Returns 409 for the Platform Admin, which cannot be deleted by any caller. Tenant Admins can only delete users within their own tenant.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
user_id |
path | string (uuid) | yes | Tenant user identifier (UUID). |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | Tenant user deleted successfully. | - |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 404 | Tenant user not found. | - |
| 409 | Conflict. The user is protected and cannot be deleted through the API. | - |
| 422 | Validation Error | HTTPValidationError |
| 500 | Internal server error. | - |
6.2 Tenant User Roles
Endpoint Summary
| Path | Summary | Method |
|---|---|---|
/api/v1/tenants/{tenant_id}/users/{user_id}/roles |
List tenant user roles | GET |
/api/v1/tenants/{tenant_id}/users/{user_id}/roles |
Set tenant user roles | PATCH |
GET /api/v1/tenants/{tenant_id}/users/{user_id}/roles
List tenant user roles
Returns the RBAC roles assigned to a tenant user.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
user_id |
path | string (uuid) | yes | Tenant user identifier (UUID). |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | User roles retrieved successfully. | RolesResponse |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 404 | Tenant user not found. | - |
| 422 | Validation Error | HTTPValidationError |
| 500 | Internal server error. | - |
Response Body (200, RolesResponse)
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
roles |
array of string | yes | n/a | ["admin"] |
Roles currently bound to the principal. |
PATCH /api/v1/tenants/{tenant_id}/users/{user_id}/roles
Set tenant user roles
Replaces the RBAC roles assigned to a tenant user. The roles of a protected user cannot be changed through the API, and the request is refused with 409.
Authentication: required (PasswordLogin or BearerJWT).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
tenant_id |
path | string (uuid) | yes | Tenant identifier (UUID). |
user_id |
path | string (uuid) | yes | Tenant user identifier (UUID). |
Request Body (application/json, required)
Schema: SetRolesRequest
Request payload for replacing the full role set of a Tenant User.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
roles |
array of string | yes | n/a | ["admin"] |
Roles to assign to the user; replaces the current set. A role the target tenant does not define, or a reserved one, is rejected with HTTP 400. |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | User roles retrieved successfully. | RolesResponse |
| 400 | Bad request. A requested role is not defined by the tenant’s RBAC policy. | - |
| 401 | Unauthorized. Authentication required. | - |
| 403 | Forbidden. Insufficient permissions. | - |
| 404 | Tenant user not found. | - |
| 409 | Conflict. The request conflicts with the current state of the resource. | - |
| 422 | Validation error. | - |
| 500 | Internal server error. | - |
Response Body (200, RolesResponse)
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
roles |
array of string | yes | n/a | ["admin"] |
Roles currently bound to the principal. |