Operation details
GET /v1/admin/users
List tenant users in the customer control plane
- operationId
listManagedUsers- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires identity.users.manage in a platform scope. Platform identities are never returned.
Parameters
listManagedUsers Parameters| Name | In | Type | Required | Description |
|---|
include | query | array<string: user_metadata / user_verification / platform_admins / reseller> | No | Optional comma-separated unique projections. user_metadata adds remark and QQ; user_verification adds only current personal/company verification flags; platform_admins also lists platform-scope administrators (tenant_id null); Omission preserves the original fifteen-field representation. Empty, unknown, duplicate items and repeated parameters are rejected. user_verification, platform_admins and reseller are accepted only on this list endpoint. |
|---|
page | query | integer | No | — |
|---|
limit | query | integer | No | — |
|---|
search | query | string | No | — |
|---|
display_id | query | string | No | Exact positive-decimal user display ID. Internal UUID identity and write paths are unchanged. |
|---|
username | query | string | No | Case-insensitive literal substring of username only. Trim boundary whitespace, reject raw C0/C1 controls, and allow at most 128 Unicode code points after trimming. Empty means no filter; all supplied filters intersect using AND. |
|---|
display_name | query | string | No | Case-insensitive literal substring of display name only, with the same trimming, control-character rejection, length and AND semantics as username. Percent and underscore are literal characters. |
|---|
email | query | string | No | Case-insensitive literal substring of email only, with the same trimming, control-character rejection, length and AND semantics as username. Partial addresses are allowed; NULL email does not match a nonempty filter. |
|---|
phone | query | string | No | Case-insensitive literal substring of phone only, with the same trimming, control-character rejection, length and AND semantics as username. Leading zeroes and plus signs are significant; NULL phone does not match a nonempty filter. |
|---|
remark | query | string | No | Trimmed case-insensitive literal substring of the administrator remark. Empty means no filter; combined with every other filter using AND. |
|---|
qq | query | string | No | Trimmed case-insensitive literal substring of the QQ contact text. Leading zeroes are significant; empty means no filter and all filters intersect. |
|---|
status | query | string: active / disabled | No | — |
|---|
real_name_status | query | string: verified / unverified | No | Optional current verification filter, intersected with all other filters before pagination in the same snapshot as the returned flags. verified means personal_verified OR company_verified; unverified means neither. Omit for all users. Empty or unknown values are invalid. Each flag requires the latest application of that kind to be approved, its authoritative identity binding to match, and its evidence settlement to be settled. Reads never create or approve identity records. |
|---|
role | query | string: tenant_owner / tenant_viewer | No | — |
|---|
group_id | query | string(uuid) | No | — |
|---|
type | query | string: reseller / customer / direct | No | reseller = the tenant has a reseller profile (active or suspended); customer = the tenant belongs to a reseller; direct = neither. Any value excludes platform administrators. Omit for all users. |
|---|
parent | query | string | No | Owning reseller filter, applied before pagination and intersected with type. none = tenants without a reseller (platform customers, including resellers themselves); a lowercase reseller scope UUID = that reseller's customers. Excludes platform administrators. Omit for all users. |
|---|
Responses
listManagedUsers Responses| Status | Description |
|---|
200 | Stable tenant user page ordered newest first. Fields:items: array<ManagedUser> page: integer limit: integer total: integer(int64) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/admin/users
Create an isolated tenant user
- operationId
createManagedUser- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Creates the tenant, tenant scope, system roles, membership, and Argon2id credential atomically.
Parameters
createManagedUser Parameters| Name | In | Type | Required | Description |
|---|
include | query | string: user_metadata | No | Set to user_metadata to include administrator-only remark and QQ fields. Omission preserves the original fifteen-field representation. Unknown or repeated values are rejected. This representation choice does not change mutation idempotency; a historical receipt may omit metadata, in which case read the current resource before editing these fields. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
X-Request-ID | header | string | No | Caller-stable write attempt identifier. Reuse it only with the same idempotency key and body. |
|---|
traceparent | header | string | No | W3C trace context preserved across an exact retry. |
|---|
Request body
application/json · Required:Yes
createManagedUser Request body| Name | Type | Required | Description |
|---|
username | string | Yes | — |
|---|
password | string(password) | Yes | 8 to 1024 printable ASCII characters (no space) with at least two of upper case, lower case, digits and symbols; otherwise password_policy_unmet. |
|---|
display_name | string | Yes | — |
|---|
email | string(email) | null(email) | No | — |
|---|
phone | string | null | No | — |
|---|
remark | string | null | No | Administrator-only remark, trimmed at both ends. Internal tabs and line breaks are preserved; other control characters are rejected. Null or whitespace-only input clears the stored value. Length counts Unicode code points. |
|---|
qq | string | null | No | Trimmed QQ contact text, preserving leading zeroes. Not a login identifier and not unique. Control characters are rejected; null or whitespace-only input clears the stored value. Length counts Unicode code points. |
|---|
role | string: tenant_owner / tenant_viewer | Yes | — |
|---|
group_id | string(uuid) | null(uuid) | No | — |
|---|
Responses
createManagedUser Responses| Status | Description |
|---|
201 | Tenant user created, or an identical idempotent request replayed. Fields:id: string(uuid) display_id: string scope_id: string(uuid) tenant_id: string(uuid) username: string display_name: string email: string(email) | null(email) phone: string | null status: string: active / disabled role: string: tenant_owner / tenant_viewer group_id: string(uuid) | null(uuid) group_name: string | null metadata?: ManagedUserMetadata verification?: ManagedUserVerification reseller?: ManagedUserReseller revision: integer(int64) created_at: string(date-time) updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
PATCH /v1/admin/users
Atomically update tenant users
- operationId
batchUpdateManagedUsers- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Applies the complete array or no changes. Disabling a user revokes every refresh family and invalidates existing access sessions immediately.
Parameters
batchUpdateManagedUsers Parameters| Name | In | Type | Required | Description |
|---|
include | query | string: user_metadata | No | Set to user_metadata to include administrator-only remark and QQ fields. Omission preserves the original fifteen-field representation. Unknown or repeated values are rejected. This representation choice does not change mutation idempotency; a historical receipt may omit metadata, in which case read the current resource before editing these fields. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
X-Request-ID | header | string | No | Caller-stable write attempt identifier. Reuse it only with the same idempotency key and body. |
|---|
traceparent | header | string | No | W3C trace context preserved across an exact retry. |
|---|
Request body
application/json · Required:Yes
Responses
batchUpdateManagedUsers Responses| Status | Description |
|---|
200 | Users updated in request order, or an identical idempotent request replayed. Fields:items: array<ManagedUser> |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
GET /v1/admin/users/{id}
Get one tenant user
- operationId
getManagedUser- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
A platform identity or an unknown tenant user produces the same 404 response.
Parameters
getManagedUser Parameters| Name | In | Type | Required | Description |
|---|
include | query | string: user_metadata | No | Set to user_metadata to include administrator-only remark and QQ fields. Omission preserves the original fifteen-field representation. Unknown or repeated values are rejected. This representation choice does not change mutation idempotency; a historical receipt may omit metadata, in which case read the current resource before editing these fields. |
|---|
id | path | string(uuid) | Yes | — |
|---|
Responses
getManagedUser Responses| Status | Description |
|---|
200 | Tenant user details. Fields:id: string(uuid) display_id: string scope_id: string(uuid) tenant_id: string(uuid) username: string display_name: string email: string(email) | null(email) phone: string | null status: string: active / disabled role: string: tenant_owner / tenant_viewer group_id: string(uuid) | null(uuid) group_name: string | null metadata?: ManagedUserMetadata verification?: ManagedUserVerification reseller?: ManagedUserReseller revision: integer(int64) created_at: string(date-time) updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
PATCH /v1/admin/users/{id}
Update tenant user profile, status, and role
- operationId
updateManagedUser- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Disabling a user revokes every refresh family and invalidates existing access sessions immediately.
Parameters
updateManagedUser Parameters| Name | In | Type | Required | Description |
|---|
include | query | string: user_metadata | No | Set to user_metadata to include administrator-only remark and QQ fields. Omission preserves the original fifteen-field representation. Unknown or repeated values are rejected. This representation choice does not change mutation idempotency; a historical receipt may omit metadata, in which case read the current resource before editing these fields. |
|---|
id | path | string(uuid) | Yes | — |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
X-Request-ID | header | string | No | Caller-stable write attempt identifier. Reuse it only with the same idempotency key and body. |
|---|
traceparent | header | string | No | W3C trace context preserved across an exact retry. |
|---|
Request body
application/json · Required:Yes
updateManagedUser Request body| Name | Type | Required | Description |
|---|
expected_revision | integer(int64) | Yes | — |
|---|
display_name | string | Yes | — |
|---|
email | string(email) | null(email) | Yes | — |
|---|
phone | string | null | Yes | — |
|---|
status | string: active / disabled | Yes | — |
|---|
remark | string | null | No | Administrator-only remark, trimmed at both ends. Internal tabs and line breaks are preserved; other control characters are rejected. Null or whitespace-only input clears the stored value. Length counts Unicode code points. |
|---|
qq | string | null | No | Trimmed QQ contact text, preserving leading zeroes. Not a login identifier and not unique. Control characters are rejected; null or whitespace-only input clears the stored value. Length counts Unicode code points. |
|---|
role | string: tenant_owner / tenant_viewer | Yes | — |
|---|
group_id | string(uuid) | null(uuid) | No | — |
|---|
Responses
updateManagedUser Responses| Status | Description |
|---|
200 | User updated, or an identical idempotent request replayed. Fields:id: string(uuid) display_id: string scope_id: string(uuid) tenant_id: string(uuid) username: string display_name: string email: string(email) | null(email) phone: string | null status: string: active / disabled role: string: tenant_owner / tenant_viewer group_id: string(uuid) | null(uuid) group_name: string | null metadata?: ManagedUserMetadata verification?: ManagedUserVerification reseller?: ManagedUserReseller revision: integer(int64) created_at: string(date-time) updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
GET /v1/admin/users/{id}/login-security
Read the selected tenant user's login security policy
- operationId
getManagedUserLoginSecurity- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires an active primary platform bearer session and identity.users.manage. API keys and impersonation sessions are rejected. A missing policy returns revision 0, none, and an empty allowlist.
Parameters
getManagedUserLoginSecurity Parameters| Name | In | Type | Required | Description |
|---|
id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant membership scope. Duplicate or unknown query parameters are rejected. |
|---|
Responses
getManagedUserLoginSecurity Responses| Status | Description |
|---|
200 | Independent policy, without user profile or contact information. Fields:user_id: string(uuid) tenant_scope_id: string(uuid) revision: integer(int64) login_verification: string: none / sms / email login_allowlist: array<string> |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
503 | A required dependency is unavailable. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.503 A dependency is unavailable: retry later with the original Idempotency-Key.
↑ Back to list
PUT /v1/admin/users/{id}/login-security
Replace a tenant user's login security policy
- operationId
updateManagedUserLoginSecurity- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Same primary-session authorization as GET. The policy uses its own revision, receipt and audit; it does not change users.revision or existing user-write receipts. All fields are required. Empty allowlist disables the source restriction; none disables the additional login code. Email/SMS require a bound contact and a configured enabled channel. Source restrictions apply to new password and code logins, not existing sessions, refresh or API keys. Once a policy is enabled, rolling back to a binary without the login gate is unsafe. The service never silently clears a policy to permit rollback.
Parameters
updateManagedUserLoginSecurity Parameters| Name | In | Type | Required | Description |
|---|
id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant membership scope. Duplicate or unknown query parameters are rejected. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
X-Request-ID | header | string | No | Caller-stable write attempt identifier. Reuse it only with the same idempotency key and body. |
|---|
traceparent | header | string | No | W3C trace context preserved across an exact retry. |
|---|
Request body
application/json · Required:Yes
updateManagedUserLoginSecurity Request body| Name | Type | Required | Description |
|---|
expected_revision | integer(int64) | Yes | — |
|---|
login_verification | string: none / sms / email | Yes | — |
|---|
login_allowlist | array<string> | Yes | IPv4/IPv6 addresses or CIDR prefixes (for example 203.0.113.0/24). Ports, zones and empty entries are rejected. The service unmaps IPv4-mapped IPv6, masks prefixes to their network, collapses full-length prefixes to the address, deduplicates and sorts. Empty clears the restriction. |
|---|
Responses
updateManagedUserLoginSecurity Responses| Status | Description |
|---|
200 | Saved policy or exact original receipt on replay. Clearing retains and increments its revision. Fields:user_id: string(uuid) tenant_scope_id: string(uuid) revision: integer(int64) login_verification: string: none / sms / email login_allowlist: array<string> |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
422 | login_security_contact_required; the selected channel has no bound contact. |
|---|
503 | A required dependency is unavailable. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.503 A dependency is unavailable: retry later with the original Idempotency-Key.
↑ Back to list
GET /v1/admin/users/{id}/secondary-verification
Read the selected tenant user's secondary identity verification request
- operationId
getManagedUserSecondaryVerification- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Same primary-session authorization as login-security. A missing request returns revision 0, disabled, expiry_action none.
Parameters
getManagedUserSecondaryVerification Parameters| Name | In | Type | Required | Description |
|---|
id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant membership scope. Duplicate or unknown query parameters are rejected. |
|---|
Responses
getManagedUserSecondaryVerification Responses| Status | Description |
|---|
200 | Request with derived completion state. Fields:user_id: string(uuid) tenant_scope_id: string(uuid) revision: integer(int64) enabled: boolean deadline: string(date-time) | null expiry_action: string: none / lock_sites requested_at: string(date-time) | null completed: boolean enforced_at: string(date-time) | null |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
503 | A required dependency is unavailable. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.503 A dependency is unavailable: retry later with the original Idempotency-Key.
↑ Back to list
PUT /v1/admin/users/{id}/secondary-verification
Replace a tenant user's secondary identity verification request
- operationId
updateManagedUserSecondaryVerification- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Own revision, receipt and audit; users.revision is unchanged. Switching it on records requested_at and enqueues the identity.secondary_verification email/SMS notice in the same transaction; editing an active request does not notify again. The user completes it with an approved personal_reverification created after requested_at. expiry_action lock_sites requires a deadline; when the deadline passes without completion the control plane stops the user's sites (disables and locks them, then republishes so the nodes stop serving them). Once the reverification is approved, or the request is switched off or its deadline moved into the future, exactly the changes it made are undone and the scope is republished; sites stopped or locked for other reasons are left as they are. Disabling requires deadline null and expiry_action none.
Parameters
updateManagedUserSecondaryVerification Parameters| Name | In | Type | Required | Description |
|---|
id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant membership scope. Duplicate or unknown query parameters are rejected. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
X-Request-ID | header | string | No | Caller-stable write attempt identifier. Reuse it only with the same idempotency key and body. |
|---|
traceparent | header | string | No | W3C trace context preserved across an exact retry. |
|---|
Request body
application/json · Required:Yes
updateManagedUserSecondaryVerification Request body| Name | Type | Required | Description |
|---|
expected_revision | integer(int64) | Yes | — |
|---|
enabled | boolean | Yes | — |
|---|
deadline | string(date-time) | null | No | — |
|---|
expiry_action | string: none / lock_sites | Yes | — |
|---|
Responses
updateManagedUserSecondaryVerification Responses| Status | Description |
|---|
200 | Saved request or exact original receipt on replay. Fields:user_id: string(uuid) tenant_scope_id: string(uuid) revision: integer(int64) enabled: boolean deadline: string(date-time) | null expiry_action: string: none / lock_sites requested_at: string(date-time) | null completed: boolean enforced_at: string(date-time) | null |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
503 | A required dependency is unavailable. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.503 A dependency is unavailable: retry later with the original Idempotency-Key.
↑ Back to list
GET /v1/admin/users/{user_id}/api-keys
List a tenant user's API key metadata
- operationId
listManagedUserAPIKeys- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Platform session-only endpoint requiring api_keys.admin.manage. Each item includes the exact persisted IP allowlist; secrets are never returned.
Parameters
listManagedUserAPIKeys Parameters| Name | In | Type | Required | Description |
|---|
user_id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant scope selected by the platform administrator. |
|---|
limit | query | integer | No | — |
|---|
status | query | string: pending_activation / active / revoked | No | — |
|---|
name | query | string | No | — |
|---|
key_id | query | string | No | — |
|---|
cursor | query | string | No | — |
|---|
offset | query | integer | No | Page-number access (canonical non-negative integer, 0-10000). Cannot be combined with cursor; an offset past the end returns empty items with total. |
|---|
usable | query | string: true | No | Only `true` is accepted. Keeps keys that can authenticate at the page snapshot: status active and expires_at absent or later than snapshot_at. An expired key keeps its active lifecycle status as history, so status=active alone does not mean usable. Combinable only with status=active or no status. Clients judge expiry against the response Date header (server clock), not their own clock. |
|---|
Responses
listManagedUserAPIKeys Responses| Status | Description |
|---|
200 | Target user's API key metadata. Fields:items: array<APIKey> next_cursor: string has_more: boolean total?: integer |
|---|
400 | Malformed JSON, UUID, revision, CIDR, duplicate or overlapping prefix, or more than 32 prefixes. Validation params expose only field indexes and counts, never any submitted CIDR, secret, digest, or matching prefix. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/admin/users/{user_id}/api-keys
Create pending API key metadata for a tenant user
- operationId
createPendingManagedUserAPIKey- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Platform session-only endpoint requiring api_keys.admin.manage. No secret is created or returned. The target user must activate the key with their own bearer session before it can authenticate. An unknown result must be retried with the unchanged body, If-Match revision, and Idempotency-Key.
Parameters
createPendingManagedUserAPIKey Parameters| Name | In | Type | Required | Description |
|---|
user_id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant scope selected by the platform administrator. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
If-Match | header | string | Yes | Collection creation precondition. Must be the quoted revision zero value. |
|---|
Request body
application/json · Required:Yes
createPendingManagedUserAPIKey Request body| Name | Type | Required | Description |
|---|
name | string | Yes | — |
|---|
scopes | array<string> | Yes | — |
|---|
ip_allowlist | array<string> | No | Canonical network CIDRs only: no host bits, zones, IPv4-mapped IPv6, duplicate prefixes, or overlaps. Empty means unrestricted. |
|---|
expires_at | string(date-time) | No | Must be in the future and no more than 366 days from the server clock. |
|---|
pending_ttl_seconds | integer(int64) | No | — |
|---|
Responses
createPendingManagedUserAPIKey Responses| Status | Description |
|---|
201 | Pending API key metadata without secret material. Fields:id: string(uuid) key_id: string key_prefix: string scope_id: string(uuid) tenant_id: string(uuid) user_id: string(uuid) name: string scopes: array<string> unavailable_scopes?: array<string> ip_allowlist: array<string> status: string: pending_activation / active / revoked pending_expires_at?: string(date-time) expires_at?: string(date-time) last_used_at?: string(date-time) activated_at?: string(date-time) revoked_at?: string(date-time) revision: integer(int64) created_at: string(date-time) updated_at: string(date-time) |
|---|
400 | Malformed JSON, UUID, revision, CIDR, duplicate or overlapping prefix, or more than 32 prefixes. Validation params expose only field indexes and counts, never any submitted CIDR, secret, digest, or matching prefix. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
503 | A required dependency is unavailable. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.503 A dependency is unavailable: retry later with the original Idempotency-Key.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/admin/users/{user_id}/api-keys/{key_id}/revoke
Revoke a tenant user's API key
- operationId
revokeManagedUserAPIKey- Auth
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Platform session-only endpoint. Administrators cannot activate, rotate, or read key secrets. The body carries the exact persisted IP allowlist. An unknown result must be retried with the unchanged body, If-Match revision, and Idempotency-Key.
Parameters
revokeManagedUserAPIKey Parameters| Name | In | Type | Required | Description |
|---|
user_id | path | string(uuid) | Yes | — |
|---|
key_id | path | string(uuid) | Yes | — |
|---|
tenant_scope_id | query | string(uuid) | Yes | Exact tenant scope selected by the platform administrator. |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
If-Match | header | string | Yes | — |
|---|
Request body
application/json · Required:Yes
revokeManagedUserAPIKey Request body| Name | Type | Required | Description |
|---|
ip_allowlist | array<string> | Yes | Canonical network CIDRs only: no host bits, zones, IPv4-mapped IPv6, duplicate prefixes, or overlaps. Empty means unrestricted. |
|---|
grant_all_scopes | boolean | No | Rotate only. When true, the rotation also replaces the key scopes with every permission the current session may grant to an API key (the simple-mode "reset key"). It is part of the idempotency binding. Other operations reject true with 400 invalid_request. |
|---|
Responses
revokeManagedUserAPIKey Responses| Status | Description |
|---|
200 | Revoked key metadata. Fields:id: string(uuid) key_id: string key_prefix: string scope_id: string(uuid) tenant_id: string(uuid) user_id: string(uuid) name: string scopes: array<string> unavailable_scopes?: array<string> ip_allowlist: array<string> status: string: pending_activation / active / revoked pending_expires_at?: string(date-time) expires_at?: string(date-time) last_used_at?: string(date-time) activated_at?: string(date-time) revoked_at?: string(date-time) revision: integer(int64) created_at: string(date-time) updated_at: string(date-time) |
|---|
400 | Malformed JSON, UUID, revision, CIDR, duplicate or overlapping prefix, or more than 32 prefixes. Validation params expose only field indexes and counts, never any submitted CIDR, secret, digest, or matching prefix. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
503 | A required dependency is unavailable. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.503 A dependency is unavailable: retry later with the original Idempotency-Key.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list