openapi: 3.0.3 info: title: User Management API version: "1.0" description: Create, search, and manage user accounts. Covers full lifecycle operations, self-service profile management, and user type schema definitions. license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html servers: - url: https://{host}:{port} variables: host: default: "localhost" port: default: "8090" tags: - name: Users description: CRUD operations for user accounts including attribute management, role assignment, and group membership. - name: users-by-path description: Create and list users within an organization unit identified by its handle path. - name: Self description: Self-service operations that the authenticated user performs on their own profile. - name: User Types description: Manage user type schemas that define the attribute structure for different user categories. - name: User Sharing description: Share a user into other organization units without copying it, and resolve where it is visible. security: - OAuth2: [system] paths: /users: get: tags: - Users summary: List users parameters: - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' - $ref: '#/components/parameters/userFilterParam' - $ref: '#/components/parameters/includeQueryParam' responses: "200": description: List of users content: application/json: schema: $ref: '#/components/schemas/UserListResponse' example: totalResults: 5 startIndex: 1 count: 3 users: - id: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 24 email: "jane.doe@example.com" mobile: "+1-650-555-1234" address: city: "Mountain View" zip: "94040" contactPreferences: - email - sms isOwnedByOU: true - id: "039bda67-a80d-4b7b-ac0f-36db85332089" ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 31 email: "john.smith@example.com" mobile: "+1-650-903-0002" address: city: "Palo Alto" zip: "94301" contactPreferences: - sms isOwnedByOU: true - id: "e1b6ba6c-deb2-4d24-87b0-bbf79fa4487c" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" type: "employee" attributes: username: "alice.wu" firstname: "Alice" lastname: "Wu" department: "Engineering" email: "alice.wu@company.inc" isOwnedByOU: true links: - href: "users?offset=3&limit=3" rel: "next" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-limit: summary: Invalid limit parameter value: code: "USR-1011" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be between 1 and 100" invalid-offset: summary: Invalid offset parameter value: code: "USR-1012" message: key: "error.userservice.invalid_offset_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_offset_parameter_description" defaultValue: "The offset parameter must be a non-negative integer" invalid-filter: summary: Invalid filter parameter value: code: "USR-1020" message: key: "error.userservice.invalid_filter_parameter" defaultValue: "Invalid filter parameter" description: key: "error.userservice.invalid_filter_parameter_description" defaultValue: "The filter format is invalid" "500": description: Internal server error post: tags: - Users summary: Create a new user requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateUserRequest' example: ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 24 email: "jane.doe@example.com" mobile: "+1-650-555-1234" address: city: "Mountain View" zip: "94040" contactPreferences: - email - sms responses: "201": description: User created content: application/json: schema: $ref: '#/components/schemas/User' example: id: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 24 email: "jane.doe@example.com" mobile: "+1-650-555-1234" address: city: "Mountain View" zip: "94040" contactPreferences: - email - sms "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USR-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed or contains invalid data" ou-not-found: summary: Organization unit not found value: code: "USR-1005" message: key: "error.userservice.organization_unit_not_found" defaultValue: "Organization unit not found" description: key: "error.userservice.organization_unit_not_found_description" defaultValue: "The specified organization unit does not exist" schema-validation-failed: summary: Schema validation failed value: code: "USR-1019" message: key: "error.userservice.schema_validation_failed" defaultValue: "Schema validation failed" description: key: "error.userservice.schema_validation_failed_description" defaultValue: "User attributes do not conform to the required schema" user-type-not-found: summary: User type not found value: code: "USR-1021" message: key: "error.userservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.userservice.user_type_not_found_description" defaultValue: "The specified user type does not exist" invalid-organization-unit: summary: Invalid organization unit ID value: code: "USR-1022" message: key: "error.userservice.invalid_organization_unit" defaultValue: "Invalid organization unit" description: key: "error.userservice.invalid_organization_unit_description" defaultValue: "Organization unit id must be specified as a valid UUID" organization-unit-mismatch: summary: Organization unit mismatch value: code: "USR-1023" message: key: "error.userservice.organization_unit_mismatch" defaultValue: "Organization unit mismatch" description: key: "error.userservice.organization_unit_mismatch_description" defaultValue: "The organization unit does not match the user type configuration" invalid-credential: summary: Invalid credential fields value: code: "USR-1024" message: key: "error.userservice.invalid_credential" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_credential_description" defaultValue: "Invalid credential fields in request" "409": description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' examples: attribute-conflict: summary: Unique attribute conflict value: code: "USR-1014" message: key: "error.userservice.attribute_conflict" defaultValue: "Attribute conflict" description: key: "error.userservice.attribute_conflict_description" defaultValue: "A user with the same unique attribute value already exists" "500": description: Internal server error /users/{id}: get: tags: - Users summary: Get a user by id parameters: - in: path name: id required: true schema: type: string format: uuid example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" - $ref: '#/components/parameters/includeQueryParam' responses: "200": description: User details content: application/json: schema: $ref: '#/components/schemas/User' example: id: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 24 email: "jane.doe@example.com" mobile: "+1-650-555-1234" address: city: "Mountain View" zip: "94040" contactPreferences: - email - sms "404": description: User not found "500": description: Internal server error put: tags: - Users summary: Update a user by id parameters: - in: path name: id required: true schema: type: string format: uuid example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateUserRequest' example: ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 25 email: "jane.doe@example.com" mobile: "+1-650-555-5678" address: city: "Mountain View" zip: "94040" contactPreferences: - email responses: "200": description: User updated, with its `status` content: application/json: schema: $ref: '#/components/schemas/User' example: id: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" ouId: "456e8400-e29b-41d4-a716-446655440001" type: "customer" attributes: age: 25 email: "jane.doe@example.com" mobile: "+1-650-555-5678" address: city: "Mountain View" zip: "94040" contactPreferences: - email "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USR-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed or contains invalid data" ou-not-found: summary: Organization unit not found value: code: "USR-1005" message: key: "error.userservice.organization_unit_not_found" defaultValue: "Organization unit not found" description: key: "error.userservice.organization_unit_not_found_description" defaultValue: "The specified organization unit does not exist" schema-validation-failed: summary: Schema validation failed value: code: "USR-1019" message: key: "error.userservice.schema_validation_failed" defaultValue: "Schema validation failed" description: key: "error.userservice.schema_validation_failed_description" defaultValue: "User attributes do not conform to the required schema" user-type-not-found: summary: User type not found value: code: "USR-1021" message: key: "error.userservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.userservice.user_type_not_found_description" defaultValue: "The specified user type does not exist" invalid-organization-unit: summary: Invalid organization unit ID value: code: "USR-1022" message: key: "error.userservice.invalid_organization_unit" defaultValue: "Invalid organization unit" description: key: "error.userservice.invalid_organization_unit_description" defaultValue: "Organization unit id must be specified as a valid UUID" organization-unit-mismatch: summary: Organization unit mismatch value: code: "USR-1023" message: key: "error.userservice.organization_unit_mismatch" defaultValue: "Organization unit mismatch" description: key: "error.userservice.organization_unit_mismatch_description" defaultValue: "The organization unit does not match the user type configuration" invalid-credential: summary: Invalid credential fields value: code: "USR-1024" message: key: "error.userservice.invalid_credential" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_credential_description" defaultValue: "Invalid credential fields in request" cannot-modify-declarative-resource: summary: Cannot modify declarative resource value: code: "USR-1025" message: key: "error.userservice.cannot_modify_declarative_resource" defaultValue: "Cannot modify declarative resource" description: key: "error.userservice.cannot_modify_declarative_resource_description" defaultValue: "The user is declarative and cannot be modified or deleted" "409": description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' examples: attribute-conflict: summary: Unique attribute conflict value: code: "USR-1014" message: key: "error.userservice.attribute_conflict" defaultValue: "Attribute conflict" description: key: "error.userservice.attribute_conflict_description" defaultValue: "A user with the same unique attribute value already exists" shared-user-move: summary: Moving a user with sharing policies to another organization unit value: code: "USR-1038" message: key: "error.userservice.shared_user_cannot_move" defaultValue: "User with sharing policies cannot be moved" description: key: "error.userservice.shared_user_cannot_move_description" defaultValue: "The user is shared into other organization units. Delete its sharing policies before moving it to another organization unit" "404": description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error delete: tags: - Users summary: Delete a user by id parameters: - in: path name: id required: true schema: type: string format: uuid example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" responses: "204": description: User deleted "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: cannot-modify-declarative-resource: summary: Cannot modify declarative resource value: code: "USR-1025" message: key: "error.userservice.cannot_modify_declarative_resource" defaultValue: "Cannot modify declarative resource" description: key: "error.userservice.cannot_modify_declarative_resource_description" defaultValue: "The user is declarative and cannot be modified or deleted" "404": description: User not found "500": description: Internal server error /users/{id}/update-credentials: post: tags: - Users summary: Update user credentials by id description: | Sets new credential values (such as passwords) for a user. Only credential fields defined in the user type schema can be updated. System-managed credentials (e.g. passkeys) are rejected. You do not need to provide all credential fields; only the fields present in the request body are updated. parameters: - in: path name: id required: true schema: type: string format: uuid example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateUserCredentialsRequest' example: credentials: password: "n3wP@ssword!" responses: "204": description: Credentials updated "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: missing-credentials: summary: Missing credentials value: code: "USR-1017" message: key: "error.userservice.missing_credentials" defaultValue: "Missing credentials" description: key: "error.userservice.missing_credentials_description" defaultValue: "At least one credential field must be provided" invalid-credential: summary: Invalid credential fields value: code: "USR-1024" message: key: "error.userservice.invalid_credential" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_credential_description" defaultValue: "Invalid credential fields in request" cannot-modify-declarative-resource: summary: Cannot modify declarative resource value: code: "USR-1025" message: key: "error.userservice.cannot_modify_declarative_resource" defaultValue: "Cannot modify declarative resource" description: key: "error.userservice.cannot_modify_declarative_resource_description" defaultValue: "The user is declarative and cannot be modified or deleted" "404": description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/{id}/groups: get: tags: - Users summary: List groups that the user belongs to parameters: - in: path name: id required: true schema: type: string format: uuid description: "The unique identifier of the user" example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' responses: "200": description: List of groups that the user belongs to content: application/json: schema: $ref: '#/components/schemas/UserGroupListResponse' example: totalResults: 3 startIndex: 1 count: 2 groups: - id: "550e8400-e29b-41d4-a716-446655440000" name: "Premium Customers" ouId: "456e8400-e29b-41d4-a716-446655440001" - id: "660e8400-e29b-41d4-a716-446655440001" name: "Mobile App Users" ouId: "456e8400-e29b-41d4-a716-446655440001" links: - href: "users/9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3/groups?offset=2&limit=2" rel: "next" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-limit: summary: Invalid limit parameter value: code: "USR-1011" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be between 1 and 100" invalid-offset: summary: Invalid offset parameter value: code: "USR-1012" message: key: "error.userservice.invalid_offset_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_offset_parameter_description" defaultValue: "The offset parameter must be a non-negative integer" "404": description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' examples: user-not-found: summary: User not found value: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" missing-user-id: summary: Missing user ID value: code: "USR-1002" message: key: "error.userservice.missing_user_id" defaultValue: "Invalid request format" description: key: "error.userservice.missing_user_id_description" defaultValue: "User ID is required" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/{id}/usages: get: tags: - Users summary: Get user usages description: | Returns the resources that reference this user, aggregated across all resource types. For example, agents that list this user as their owner. This endpoint is informational only — it drives the pre-delete confirmation dialog in the UI and does not gate deletion on the server. Each usage entry includes a `behaviorOnDelete` field describing what happens to the referencing resource if the user is deleted: - `fallback`: the reference is kept as-is. - `cascade`: the resource is permanently deleted along with the user. When usage data is unavailable (e.g. the server has not fully initialised), `totalResults` and `summary` are `null` rather than `0`/empty. Consumers must treat `null` as "unknown" and `0` as "confirmed empty". parameters: - in: path name: id required: true schema: type: string format: uuid description: "The unique identifier of the user" example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" responses: "200": description: Resources that reference this user content: application/json: schema: $ref: '#/components/schemas/ResourceUsagesResponse' example: totalResults: 2 count: 2 summary: agent: 2 usages: - resourceType: agent id: "a1b2c3d4-0000-0000-0000-000000000001" displayName: "Support Agent" behaviorOnDelete: fallback - resourceType: agent id: "a1b2c3d4-0000-0000-0000-000000000002" displayName: "Billing Agent" behaviorOnDelete: fallback "404": description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/{id}/sharing-policies: parameters: - $ref: '#/components/parameters/userIdPathParam' post: tags: - User Sharing summary: Create a sharing policy description: | Records one organization unit's decision about which other organization units this user is shared into. The user is not copied: the same identity becomes visible in the organization units the policy reaches, and keeps living in its own. Exactly one policy exists per user per initiating organization unit; a second create is refused. The caller must be allowed to update users in the initiating organization unit: the user's own unit for a share, or, for a reshare, a unit the user was already shared into. A user cannot share itself. A user declared in a resource file declares its owner's policy there too, so this endpoint refuses one for it. An organization unit the declared policy shares with can still record its own reshare here, unless users are configured to load from resource files only: then all of their sharing, reshares included, is declared, and this endpoint refuses every policy. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicyRequest' examples: allChildUnits: summary: Every organization unit beneath the issuer value: childUnits: mode: all allChildUnitsWithExclusion: summary: Every organization unit beneath the issuer except one branch value: childUnits: mode: all excludedOuIds: ["acme-trial-customers"] selectedChildUnits: summary: Named children, one at a time value: childUnits: mode: selected units: - ouId: "acme-customer-a" reach: unit - ouId: "acme-customer-b" reach: unit childAndItsSubtree: summary: One direct child and everything beneath it value: childUnits: mode: selected units: - ouId: "acme-customer-a" reach: subtree selectedRoots: summary: Named roots of other trees, owner only value: otherTreeRoots: mode: selected units: - ouId: "partner-root" childUnitsAndRoots: summary: Child units and roots of other trees together, owner only value: childUnits: mode: all otherTreeRoots: mode: selected units: - ouId: "partner-root" reshare: summary: A reshare issued by a sharee value: initiatingOuId: "acme-customer-a" childUnits: mode: selected units: - ouId: "acme-customer-a-eu" reach: unit responses: "201": description: Sharing policy created content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicy' example: id: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" initiatingOuId: "acme-root" stage: share isReadOnly: false version: 1 childUnits: mode: all excludedOuIds: ["acme-trial-customers"] "400": $ref: '#/components/responses/UserSharingPolicyCreateBadRequest' "404": $ref: '#/components/responses/SharingUserNotFound' "409": $ref: '#/components/responses/UserSharingPolicyConflict' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' get: tags: - User Sharing summary: List sharing policies description: | Returns the user's sharing policies. A caller allowed to read users in the user's own organization unit sees every policy; any other caller sees only the policies its own organization units issued. parameters: - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' responses: "200": description: Sharing policies content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicyListResponse' example: totalResults: 2 startIndex: 1 count: 2 policies: # The owner's decision: customer A on its own, and customer B with # everything beneath it. - id: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" initiatingOuId: "acme-root" stage: share isReadOnly: false version: 2 childUnits: mode: selected units: - ouId: "acme-customer-a" reach: unit - ouId: "acme-customer-b" reach: subtree # Customer A carrying the user one hop further, which only a unit the # owner's grant stops at may do. It names the policy that reached it. - id: "0195a2c0-7b41-7c66-8f03-9d1e6a2b4c57" initiatingOuId: "acme-customer-a" stage: reshare parentPolicyId: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" isReadOnly: false version: 1 childUnits: mode: selected units: - ouId: "acme-customer-a-eu" reach: unit "400": $ref: '#/components/responses/UserSharingPolicyListBadRequest' "404": $ref: '#/components/responses/SharingUserNotFound' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' /users/{id}/sharing-policies/{policyId}: parameters: - $ref: '#/components/parameters/userIdPathParam' - $ref: '#/components/parameters/userSharingPolicyIdPathParam' get: tags: - User Sharing summary: Get a sharing policy responses: "200": description: Sharing policy content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicy' example: id: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" initiatingOuId: "acme-root" stage: share isReadOnly: false version: 2 childUnits: mode: all excludedOuIds: ["acme-trial-customers"] "404": $ref: '#/components/responses/UserSharingPolicyNotFound' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' put: tags: - User Sharing summary: Replace a sharing policy description: | Replaces the policy's sections. The request carries the `version` the caller believes it is editing; an edit against a stale version is refused rather than silently flattening another write. Each section is held to the rule on its own. A section that reaches a whole group (`mode: all`, or `allUnits`) keeps that reach: its exclusions can be added or removed, but it cannot be dropped or turned into one that names units. A section that names units may add or drop them or change their `reach`, and cannot become one that reaches a whole group. No edit may reach past an organization unit that has already shared the user on. This holds for `allUnits` and for `otherTreeRoots` with `mode: all` too, which a create may not state. A policy that was imported with one keeps it: restate the section here and rewrite its `excludedOuIds` to withhold units from it or hand them back. Editing a narrower policy into one of those is refused, so the edit cannot reach where the create could not. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicyUpdateRequest' examples: addAnExclusion: summary: Exclude one organization unit from every child unit value: version: 1 childUnits: mode: all excludedOuIds: ["acme-trial-customers"] widenANamedUnit: summary: Carry the user on beneath a named child value: version: 1 childUnits: mode: selected units: - ouId: "acme-customer-a" reach: subtree excludeFromAllUnits: summary: Rewrite the exclusions on an imported deployment-wide policy description: | The section is restated, which is what lets its exclusions move. A create may not state `allUnits`, and an edit may not introduce it. value: version: 2 allUnits: excludedOuIds: ["acme-trial-customers", "partner-sandbox"] responses: "200": description: Sharing policy replaced content: application/json: schema: $ref: '#/components/schemas/UserSharingPolicy' example: id: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" initiatingOuId: "acme-root" stage: share isReadOnly: false version: 2 childUnits: mode: all excludedOuIds: ["acme-trial-customers"] "400": $ref: '#/components/responses/UserSharingPolicyUpdateBadRequest' "404": $ref: '#/components/responses/UserSharingPolicyNotFound' "409": $ref: '#/components/responses/UserSharingPolicyConflict' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' delete: tags: - User Sharing summary: Delete a sharing policy description: | Removes the policy and everything that depended on it: the policies its sharees issued, and the per-organization-unit state of every unit that loses sight of the user. A declared policy cannot be deleted here. Its existence belongs to the resource file that declares it, so it goes away by being removed from that file. responses: "204": description: | Sharing policy deleted, or the user holds no policy under that id. "400": $ref: '#/components/responses/UserSharingPolicyDeleteBadRequest' "404": $ref: '#/components/responses/SharingUserNotFound' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' /users/{id}/overlay-rules: parameters: - $ref: '#/components/parameters/userIdPathParam' get: tags: - User Sharing summary: Overlay rules for an organization unit description: | Answers for one organization unit, named in the `ouId` query parameter: whether it owns the user, which policies reached it, and the `roles` rule when a share mandates roles for the user there. An organization unit no policy reaches answers `404`, because the user is not available there and so has no terms to resolve. parameters: - in: query name: ouId required: true description: The organization unit to resolve for. schema: type: string example: "acme-customer-a" responses: "200": description: Resolved overlay content: application/json: schema: $ref: '#/components/schemas/UserResolvedOverlay' examples: reached: summary: An organization unit a policy reached value: ouId: "acme-customer-a" isOwnedByOU: false visible: true policyIds: ["0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10"] rules: {} mandatedRoles: summary: An organization unit a share mandates roles in value: ouId: "acme-customer-a" isOwnedByOU: false visible: true policyIds: ["0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10"] rules: roles: editable: false value: ["0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a11"] owner: summary: The organization unit that owns the user value: ouId: "acme-root" isOwnedByOU: true visible: true policyIds: [] rules: {} "400": $ref: '#/components/responses/UserOverlayRulesBadRequest' "404": $ref: '#/components/responses/UserOverlayNotResolvable' "403": $ref: '#/components/responses/SharingForbidden' "500": $ref: '#/components/responses/UserSharingServerError' /users/tree/{path}: get: tags: - users-by-path summary: List users in organization unit specified by handle path description: | Lists the users the organization unit owns, followed by the users shared into it. Each listed user's `isOwnedByOU` field says which of the two it is. parameters: - in: path name: path required: true schema: type: string style: simple explode: false description: | Hierarchical path of organization unit handles separated by forward slashes. Examples: - `engineering` - Lists users in the "engineering" OU - `engineering/frontend` - Lists users in "engineering/frontend" example: "engineering/frontend" - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' - $ref: '#/components/parameters/includeQueryParam' responses: "200": description: List of users in the organization unit content: application/json: schema: $ref: '#/components/schemas/UserListResponse' example: totalResults: 5 startIndex: 1 count: 2 users: - id: "7a4b1f8e-5c69-4b60-9232-2b0aaf65ef3c" ouId: "b2c5e8f1-4a7d-4c3e-9f60-1d8a2e5b7c94" type: "employee" attributes: username: "maya.perera" email: "maya.perera@company.inc" isOwnedByOU: true - id: "9f1e47d3-0347-4464-9f02-e0bfae02e896" ouId: "b2c5e8f1-4a7d-4c3e-9f60-1d8a2e5b7c94" type: "employee" attributes: username: "ravi.kumar" email: "ravi.kumar@company.inc" isOwnedByOU: false links: - href: "users/tree/engineering/frontend?offset=10&limit=10" rel: "next" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-limit: summary: Invalid limit parameter value: code: "USR-1011" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be between 1 and 100" invalid-offset: summary: Invalid offset parameter value: code: "USR-1012" message: key: "error.userservice.invalid_offset_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_offset_parameter_description" defaultValue: "The offset parameter must be a non-negative integer" invalid-filter: summary: Invalid filter parameter value: code: "USR-1020" message: key: "error.userservice.invalid_filter_parameter" defaultValue: "Invalid filter parameter" description: key: "error.userservice.invalid_filter_parameter_description" defaultValue: "The filter format is invalid" "404": description: Organization unit not found content: application/json: schema: $ref: '#/components/schemas/Error' examples: path-not-found: summary: Handle path not found value: code: "USR-1005" message: key: "error.userservice.organization_unit_not_found" defaultValue: "Organization unit not found" description: key: "error.userservice.organization_unit_not_found_description" defaultValue: "The organization unit with the specified handle path does not exist" invalid-path: summary: Invalid path structure value: code: "USR-1009" message: key: "error.userservice.invalid_handle_path" defaultValue: "Invalid handle path" description: key: "error.userservice.invalid_handle_path_description" defaultValue: "The handle path does not represent a valid organizational hierarchy" "500": description: Internal server error content: text/plain: schema: type: string example: "Internal server error" post: tags: - users-by-path summary: Create a new user under the organization unit specified by the handle path parameters: - in: path name: path required: true schema: type: string style: simple explode: false description: | Hierarchical path of organization unit handles separated by forward slashes. The new user will be created under the organization unit specified by this path. Examples: - `engineering` - Creates a new user under the "engineering" OU - `engineering/frontend` - Creates a new user under "engineering/frontend" example: "engineering/frontend" requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateUserByPathRequest' example: type: "employee" attributes: username: "john.doe" firstname: "John" lastname: "Doe" email: "john.doe@company.com" department: "Engineering" responses: "201": description: User created content: application/json: schema: $ref: '#/components/schemas/User' example: id: "7a4b1f8e-5c69-4b60-9232-2b0aaf65ef3c" ouId: "a839f4bd-39dc-4eaa-b5cc-210d8ecaee87" type: "employee" attributes: username: "john.doe" firstname: "John" lastname: "Doe" email: "john.doe@company.com" department: "Engineering" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USR-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed, contains invalid data, or required fields are missing/empty" schema-validation-failed: summary: Schema validation failed value: code: "USR-1019" message: key: "error.userservice.schema_validation_failed" defaultValue: "Schema validation failed" description: key: "error.userservice.schema_validation_failed_description" defaultValue: "User attributes do not conform to the required schema" user-type-not-found: summary: User type not found value: code: "USR-1021" message: key: "error.userservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.userservice.user_type_not_found_description" defaultValue: "The specified user type does not exist" organization-unit-mismatch: summary: Organization unit mismatch value: code: "USR-1023" message: key: "error.userservice.organization_unit_mismatch" defaultValue: "Organization unit mismatch" description: key: "error.userservice.organization_unit_mismatch_description" defaultValue: "The organization unit does not match the user type configuration" invalid-credential: summary: Invalid credential fields value: code: "USR-1024" message: key: "error.userservice.invalid_credential" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_credential_description" defaultValue: "Invalid credential fields in request" "404": description: Organization unit not found content: application/json: schema: $ref: '#/components/schemas/Error' examples: path-not-found: summary: Handle path not found value: code: "USR-1005" message: key: "error.userservice.organization_unit_not_found" defaultValue: "Organization unit not found" description: key: "error.userservice.organization_unit_not_found_description" defaultValue: "The organization unit with the specified handle path does not exist" invalid-path: summary: Invalid path structure value: code: "USR-1009" message: key: "error.userservice.invalid_handle_path" defaultValue: "Invalid handle path" description: key: "error.userservice.invalid_handle_path_description" defaultValue: "The handle path does not represent a valid organizational hierarchy" "409": description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' examples: username-conflict: summary: Unique attribute conflict value: code: "USR-1014" message: key: "error.userservice.attribute_conflict" defaultValue: "Attribute conflict" description: key: "error.userservice.attribute_conflict_description" defaultValue: "A user with the same unique attribute value already exists" "500": description: Internal server error content: text/plain: schema: type: string example: "Internal server error" /users/me: get: tags: - Self summary: Get self user profile security: - OAuth2: [] responses: "200": description: User details content: application/json: schema: $ref: '#/components/schemas/User' example: id: "e1b6ba6c-deb2-4d24-87b0-bbf79fa4487c" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" type: "employee" attributes: username: "alice.wu" firstname: "Alice" lastname: "Wu" email: "alice.wu@company.inc" "401": description: Unauthorized - missing or invalid authentication token content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "AUTH-4010" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "Authentication is required to access this resource" "404": description: Authenticated user not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" put: tags: - Self summary: Update self user profile security: - OAuth2: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateSelfUserRequest' example: attributes: username: "alice.wu" firstname: "Alice" lastname: "Wu" email: "alice.wu@company.io" responses: "200": description: User updated, with its `status` content: application/json: schema: $ref: '#/components/schemas/User' example: id: "e1b6ba6c-deb2-4d24-87b0-bbf79fa4487c" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" type: "employee" attributes: username: "alice.wu" firstname: "Alice" lastname: "Wu" email: "alice.wu@company.io" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USR-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed or contains invalid data" schema-validation-failed: summary: Schema validation failed value: code: "USR-1019" message: key: "error.userservice.schema_validation_failed" defaultValue: "Schema validation failed" description: key: "error.userservice.schema_validation_failed_description" defaultValue: "User attributes do not conform to the required schema" user-type-not-found: summary: User type not found value: code: "USR-1021" message: key: "error.userservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.userservice.user_type_not_found_description" defaultValue: "The specified user type does not exist" "401": description: Unauthorized - missing or invalid authentication token content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "AUTH-4010" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "Authentication is required to access this resource" "404": description: Authenticated user not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "409": description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1014" message: key: "error.userservice.attribute_conflict" defaultValue: "Attribute conflict" description: key: "error.userservice.attribute_conflict_description" defaultValue: "A user with the same unique attribute value already exists" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/me/meta: get: tags: - Self summary: Get self user schema metadata security: - OAuth2: [] responses: "200": description: Schema metadata for the caller's user type content: application/json: schema: type: object required: [schema] properties: schema: $ref: '#/components/schemas/UserType/properties/schema' "400": description: User type schema missing or not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1021" message: key: "error.userservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.userservice.user_type_not_found_description" defaultValue: "The specified user type does not exist" "401": description: Unauthorized - missing or invalid authentication token content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "AUTH-4010" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "Authentication is required to access this resource" "404": description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/me/ous: get: tags: - Self summary: List the organization units the caller can access description: | Lists the organization units the signed-in user can access: the one the user lives in and every one the user is shared into, directly or through a reshare. `current` is the organization unit the list is relative to: the one the caller's token was issued for, or the user's own when the token names none. It is returned whatever the scope or page, because the units a scope selects may not include it. security: - OAuth2: [] parameters: - in: query name: scope required: false description: | Narrows the list, relative to `current`. When omitted, every accessible organization unit is listed. - `siblings`: `current` and the accessible units that share its parent. The parent itself is not listed. When `current` is a top-level unit, its siblings are the other accessible top-level units. schema: type: string enum: [siblings] - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' responses: "200": description: Organization units the caller can access content: application/json: schema: $ref: '#/components/schemas/AccessibleOrganizationUnitListResponse' examples: every-unit: summary: No scope; the user lives in the Customers unit, signed in for Acme OU 1 value: current: "7b6a5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d" totalResults: 3 startIndex: 1 count: 3 organizationUnits: - id: "4f3c2a1b-0d9e-4c8b-9a7f-6e5d4c3b2a10" handle: "customers" name: "Customers" - id: "7b6a5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d" handle: "acme-ou-1" name: "Acme OU 1" - id: "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b" handle: "acme-ou-2" name: "Acme OU 2" links: [] siblings: summary: scope=siblings, for the same user and token value: current: "7b6a5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d" totalResults: 2 startIndex: 1 count: 2 organizationUnits: - id: "7b6a5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d" handle: "acme-ou-1" name: "Acme OU 1" - id: "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b" handle: "acme-ou-2" name: "Acme OU 2" links: [] "400": description: Invalid scope or pagination parameter content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-scope: summary: A scope this endpoint does not offer value: code: "USR-1036" message: key: "error.userservice.invalid_scope_parameter" defaultValue: "Invalid scope parameter" description: key: "error.userservice.invalid_scope_parameter_description" defaultValue: "The scope parameter, when given, must be siblings" invalid-limit: summary: A limit outside its bounds value: code: "USR-1011" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be a positive integer" "401": description: Unauthorized - missing or invalid authentication token content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "AUTH-4010" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "Authentication is required to access this resource" "404": description: | Authenticated user not found. A token issued to an application or an agent rather than a user is answered this way too. content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /users/me/update-credentials: post: tags: - Self summary: Update self user credentials security: - OAuth2: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateSelfUserRequest' example: attributes: password: "n3wP@ssword!" responses: "204": description: Credentials updated "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: missing-credentials: summary: Missing credentials value: code: "USR-1017" message: key: "error.userservice.missing_credentials" defaultValue: "Missing credentials" description: key: "error.userservice.missing_credentials_description" defaultValue: "At least one credential field must be provided" "401": description: Unauthorized - missing or invalid authentication token content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "AUTH-4010" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "Authentication is required to access this resource" "404": description: Authenticated user not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" "500": description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" /user-types: get: tags: - User Types summary: List user type schemas description: | Retrieves a list of all user type schemas that define the structure and attributes for different user types. parameters: - $ref: '#/components/parameters/limitQueryParam' - $ref: '#/components/parameters/offsetQueryParam' - $ref: '#/components/parameters/includeQueryParam' responses: "200": description: List of user type schemas content: application/json: schema: $ref: '#/components/schemas/UserTypeListResponse' example: totalResults: 3 startIndex: 1 count: 3 types: - id: "660e8400-e29b-41d4-a716-446655440001" handle: "employee" displayName: "Employee" ouId: "a839f4bd-39dc-4eaa-b5cc-210d8ecaee87" allowSelfRegistration: false systemAttributes: display: "username" - id: "550e8400-e29b-41d4-a716-446655440000" handle: "customer" displayName: "Customer" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: true systemAttributes: display: "email" - id: "770e8400-e29b-41d4-a716-446655440002" handle: "partner" displayName: "Partner" ouId: "770e8400-e29b-41d4-a716-446655440002" allowSelfRegistration: false systemAttributes: display: "email" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-limit: summary: Invalid limit parameter value: code: "USRS-1005" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be between 1 and 100" invalid-offset: summary: Invalid offset parameter value: code: "USRS-1006" message: key: "error.userservice.invalid_offset_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_offset_parameter_description" defaultValue: "The offset parameter must be a non-negative integer" "500": description: Internal server error post: tags: - User Types summary: Create a new user type schema description: | Creates a new user type schema that defines the structure and attributes for a specific user type. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateUserTypeRequest' example: handle: "partner" displayName: "Partner" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: false systemAttributes: display: "email" schema: firstname: type: "string" lastname: type: "string" required: true email: type: "string" required: true unique: true password: type: "string" required: true credential: true company: type: "string" role: type: "string" partnershipType: type: "string" enum: ["technology", "business", "strategic"] phoneNumber: type: "string" responses: "201": description: User type created content: application/json: schema: $ref: '#/components/schemas/UserType' example: id: "880e8400-e29b-41d4-a716-446655440003" handle: "partner" displayName: "Partner" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: false systemAttributes: display: "email" schema: firstname: type: "string" lastname: type: "string" required: true email: type: "string" required: true unique: true password: type: "string" required: true credential: true company: type: "string" role: type: "string" partnershipType: type: "string" enum: ["technology", "business", "strategic"] phoneNumber: type: "string" "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USRS-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed or contains invalid data" invalid-attribute-definition: summary: Invalid attribute definition value: code: "USRS-1004" message: key: "error.entitytypeservice.invalid_user_type_request" defaultValue: "Invalid user type request" description: key: "error.entitytypeservice.invalid_user_type_request_description" defaultValue: "One or more attribute definitions are invalid" invalid-handle: summary: Invalid handle value: code: "USRS-1016" message: key: "error.entitytypeservice.invalid_entity_type_handle" defaultValue: "Invalid entity type handle" description: key: "error.entitytypeservice.invalid_entity_type_handle_description" defaultValue: "The handle must contain only lowercase letters, numbers, hyphens and underscores, and must start and end with a letter or a number" "409": description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USRS-1003" message: key: "error.entitytypeservice.user_type_handle_conflict" defaultValue: "User type handle conflict" description: key: "error.entitytypeservice.user_type_handle_conflict_description" defaultValue: "A user type with the same handle already exists" "500": description: Internal server error /user-types/{id}: get: tags: - User Types summary: Get a user type schema by ID description: | Retrieves the details of a specific user type schema by its ID. parameters: - in: path name: id required: true schema: type: string format: uuid example: "550e8400-e29b-41d4-a716-446655440000" - $ref: '#/components/parameters/includeQueryParam' responses: "200": description: User type details content: application/json: schema: $ref: '#/components/schemas/UserType' examples: simple: summary: Employee schema with simple attributes value: id: "660e8400-e29b-41d4-a716-446655440001" handle: "employee" displayName: "Employee" ouId: "a839f4bd-39dc-4eaa-b5cc-210d8ecaee87" allowSelfRegistration: false systemAttributes: display: "username" schema: firstname: type: "string" lastname: type: "string" required: true username: type: "string" required: true unique: true password: type: "string" required: true credential: true regex: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]).{8,}$" employeeId: type: "number" unique: true department: type: "string" enum: ["Engineering", "Marketing", "Sales", "HR", "Finance", "Operations"] isActive: type: "boolean" complex: summary: Customer schema with complex attributes value: id: "550e8400-e29b-41d4-a716-446655440000" handle: "customer" displayName: "Customer" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: true systemAttributes: display: "email" schema: email: type: "string" required: true unique: true regex: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" mobile: type: "string" regex: "^\\+?[1-9]\\d{1,14}$" address: type: "object" required: true properties: street: type: "string" city: type: "string" required: true zipCode: type: "string" regex: "^\\d{5}(-\\d{4})?$" country: type: "string" contactPreferences: type: "array" items: type: "string" enum: ["email", "sms", "phone", "mail"] "404": description: User type not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USRS-1002" message: key: "error.entitytypeservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.entitytypeservice.user_type_not_found_description" defaultValue: "The user type with the specified id does not exist" "500": description: Internal server error put: tags: - User Types summary: Update a user type schema by ID description: | Updates an existing user type schema with new attribute definitions. This operation replaces the entire schema definition. The handle is optional. When provided, it must match the existing handle of the user type. The display name can be changed at any time. parameters: - in: path name: id required: true schema: type: string format: uuid example: "550e8400-e29b-41d4-a716-446655440000" requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateUserTypeRequest' example: handle: "customer" displayName: "Customer" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: true systemAttributes: display: "email" schema: email: type: "string" required: true unique: true password: type: "string" required: true credential: true age: type: "number" mobile: type: "string" preferredLanguage: type: "string" enum: ["en", "es", "fr", "de", "it"] loyaltyTier: type: "string" enum: ["bronze", "silver", "gold", "platinum"] responses: "200": description: User type updated content: application/json: schema: $ref: '#/components/schemas/UserType' example: id: "550e8400-e29b-41d4-a716-446655440000" handle: "customer" displayName: "Customer" ouId: "26eec421-f1bb-4deb-a5d3-9ab6554c2ae6" allowSelfRegistration: true systemAttributes: display: "email" schema: email: type: "string" required: true unique: true password: type: "string" required: true credential: true age: type: "number" mobile: type: "string" preferredLanguage: type: "string" enum: ["en", "es", "fr", "de", "it"] loyaltyTier: type: "string" enum: ["bronze", "silver", "gold", "platinum"] "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalid-request-format: summary: Invalid request format value: code: "USRS-1001" message: key: "error.userservice.invalid_request_format" defaultValue: "Invalid request format" description: key: "error.userservice.invalid_request_format_description" defaultValue: "The request body is malformed or contains invalid data" invalid-attribute-definition: summary: Invalid attribute definition value: code: "USRS-1004" message: key: "error.entitytypeservice.invalid_user_type_request" defaultValue: "Invalid user type request" description: key: "error.entitytypeservice.invalid_user_type_request_description" defaultValue: "One or more attribute definitions are invalid" handle-update-not-allowed: summary: Handle cannot be changed value: code: "USRS-1017" message: key: "error.entitytypeservice.entity_type_handle_update_not_allowed" defaultValue: "Entity type handle cannot be changed" description: key: "error.entitytypeservice.entity_type_handle_update_not_allowed_description" defaultValue: "The handle of an entity type cannot be changed once it is created" "404": description: User type not found content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USRS-1002" message: key: "error.entitytypeservice.user_type_not_found" defaultValue: "User type not found" description: key: "error.entitytypeservice.user_type_not_found_description" defaultValue: "The user type with the specified id does not exist" "500": description: Internal server error delete: tags: - User Types summary: Delete a user type schema by ID description: | Deletes a user type schema. This operation will fail if there are existing users of this type. parameters: - in: path name: id required: true schema: type: string format: uuid example: "550e8400-e29b-41d4-a716-446655440000" responses: "204": description: User type deleted "400": description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USRS-1004" message: key: "error.entitytypeservice.invalid_user_type_request" defaultValue: "Invalid user type request" description: key: "error.entitytypeservice.invalid_user_type_request_description" defaultValue: "Cannot delete schema because users of this type exist" "500": description: Internal server error components: securitySchemes: OAuth2: type: oauth2 flows: authorizationCode: authorizationUrl: https://localhost:8090/oauth2/authorize tokenUrl: https://localhost:8090/oauth2/token scopes: system: Access to system management APIs clientCredentials: tokenUrl: https://localhost:8090/oauth2/token scopes: system: Access to system management APIs parameters: limitQueryParam: in: query name: limit required: false description: | Maximum number of records to return. Must be between 1 and 100 inclusive. schema: type: integer minimum: 1 maximum: 100 default: 30 offsetQueryParam: in: query name: offset required: false description: | Number of records to skip for pagination. Must be a non-negative integer. schema: type: integer minimum: 0 default: 0 includeQueryParam: in: query name: include required: false schema: type: string enum: - display description: | Optional parameter to include additional display information in the response. The exact fields included depend on the endpoint. See each endpoint's response schema for details on which fields are enriched. userFilterParam: in: query name: filter required: false description: | Filter users by attribute values. Supported operators: eq (ie. equals). Format: `attribute operator "value"`. Examples: - `username eq "john.doe"` - Users with username = "john.doe"' - `age eq 25` - Users with age = 25 - `address.city eq "Mountain View"` - Users with address.city = "Mountain View" - `ouId eq "456e8400-e29b-41d4-a716-446655440001"` - Users the organization unit owns, followed by the users shared into it. schema: type: string examples: organization-unit: summary: Users owned by or shared into an organization unit value: 'ouId eq "456e8400-e29b-41d4-a716-446655440001"' simple-string: summary: Simple string filter value: 'username eq "john.doe"' simple-number: summary: Simple number filter value: 'age eq 25' complex: summary: Complex filtering value: 'address.city eq "Mountain View"' userIdPathParam: in: path name: id required: true description: User ID schema: type: string format: uuid example: "9a475e1e-b0cb-4b29-8df5-2e5b24fb0ed3" userSharingPolicyIdPathParam: in: path name: policyId required: true description: Sharing policy ID schema: type: string example: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" responses: UserSharingPolicyCreateBadRequest: description: | The policy is not one the issuing organization unit may write. The code says which kind of mistake it is, and the description says what is wrong with this request in particular. content: application/json: schema: $ref: '#/components/schemas/Error' examples: declaredUser: summary: The owner's policy of a user declared in a resource file value: code: "USR-1025" message: key: "error.userservice.cannot_modify_declarative_resource" defaultValue: "Cannot modify declarative resource" description: key: "error.userservice.cannot_modify_declarative_resource_description" defaultValue: "The user is declarative and cannot be modified or deleted" noSection: summary: No section stated value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_request_format_description" defaultValue: "The request body is malformed, reaches no organization unit, or states a section with fields its mode does not take: the policy reaches no organization unit" fieldTheModeDoesNotTake: summary: A section carrying a field its mode does not take value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_request_format_description" defaultValue: "The request body is malformed, reaches no organization unit, or states a section with fields its mode does not take: childUnits with mode all takes no units" unitNamedTwice: summary: An organization unit named twice, or one the issuer may not name value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_target_ou_description" defaultValue: "The target organization unit does not satisfy the policy's constraints: acme-customer-a is named more than once" rolesNotOnNamedUnit: summary: A roles rule anywhere but on a named child unit with reach unit value: code: "USR-1039" message: key: "error.userservice.roles_not_on_named_unit" defaultValue: "Roles can be mandated only on named child units" description: key: "error.userservice.roles_not_on_named_unit_description" defaultValue: "Set the roles rule on a unit listed under childUnits in selected mode with reach unit, not on a subtree or on a section that reaches every unit" rolesRuleNotFixed: summary: A roles rule that lists no role, or carries excludedValues value: code: "USR-1040" message: key: "error.userservice.roles_rule_not_fixed" defaultValue: "Invalid roles rule" description: key: "error.userservice.roles_rule_not_fixed_description" defaultValue: "A roles rule must list at least one role in value, without excludedValues" mandatedRolesNotSupported: summary: Roles mandated while roles load only from resource files value: code: "ROL-1038" message: key: "error.roleservice.mandated_roles_not_supported" defaultValue: "Mandated roles are not supported" description: key: "error.roleservice.mandated_roles_not_supported_description" defaultValue: "Roles load only from declarative resource files, so a sharing policy cannot mandate them. Use the mutable or composite role store" mandatedRoleNotInOU: summary: A mandated role the organization unit neither owns nor has shared with it value: code: "ROL-1035" message: key: "error.roleservice.mandated_role_not_in_ou" defaultValue: "Role is not available in the organization unit" description: key: "error.roleservice.mandated_role_not_in_ou_description" defaultValue: "A sharing policy can only mandate a role in an organization unit that owns the role or has it shared with it" deploymentWideReach: summary: A reach this endpoint may not create value: code: "USR-1037" message: key: "error.userservice.deployment_wide_sharing_not_allowed" defaultValue: "Deployment-wide sharing is not allowed" description: key: "error.userservice.deployment_wide_sharing_not_allowed_description" defaultValue: "A policy reaching all organization units or the roots of all other trees can only be created from a declarative resource file or an import" UserSharingPolicyListBadRequest: description: The page the listing asked for is not one it can return. content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalidPage: summary: A limit or offset outside its bounds, or not a number at all description: | A value this endpoint cannot parse and one the sharing framework refuses answer the same way, so a caller sees one error for one mistake. value: code: "USR-1011" message: key: "error.userservice.invalid_limit_parameter" defaultValue: "Invalid pagination parameter" description: key: "error.userservice.invalid_limit_parameter_description" defaultValue: "The limit parameter must be a positive integer" UserSharingPolicyUpdateBadRequest: description: | The replacement is not one this policy may become. Alongside the mistakes a create can make, an edit answers for the reach the policy already has. content: application/json: schema: $ref: '#/components/schemas/Error' examples: noSection: summary: No section stated value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_request_format_description" defaultValue: "The request body is malformed, reaches no organization unit, or states a section with fields its mode does not take: the policy reaches no organization unit" fieldTheModeDoesNotTake: summary: A section carrying a field its mode does not take value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_request_format_description" defaultValue: "The request body is malformed, reaches no organization unit, or states a section with fields its mode does not take: childUnits with mode all takes no units" unitNamedTwice: summary: An organization unit named twice, or one the issuer may not name value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.invalid_target_ou_description" defaultValue: "The target organization unit does not satisfy the policy's constraints: acme-customer-a is named more than once" rolesNotOnNamedUnit: summary: A roles rule anywhere but on a named child unit with reach unit value: code: "USR-1039" message: key: "error.userservice.roles_not_on_named_unit" defaultValue: "Roles can be mandated only on named child units" description: key: "error.userservice.roles_not_on_named_unit_description" defaultValue: "Set the roles rule on a unit listed under childUnits in selected mode with reach unit, not on a subtree or on a section that reaches every unit" rolesRuleNotFixed: summary: A roles rule that lists no role, or carries excludedValues value: code: "USR-1040" message: key: "error.userservice.roles_rule_not_fixed" defaultValue: "Invalid roles rule" description: key: "error.userservice.roles_rule_not_fixed_description" defaultValue: "A roles rule must list at least one role in value, without excludedValues" mandatedRolesNotSupported: summary: Roles mandated while roles load only from resource files value: code: "ROL-1038" message: key: "error.roleservice.mandated_roles_not_supported" defaultValue: "Mandated roles are not supported" description: key: "error.roleservice.mandated_roles_not_supported_description" defaultValue: "Roles load only from declarative resource files, so a sharing policy cannot mandate them. Use the mutable or composite role store" mandatedRoleNotInOU: summary: A mandated role the organization unit neither owns nor has shared with it value: code: "ROL-1035" message: key: "error.roleservice.mandated_role_not_in_ou" defaultValue: "Role is not available in the organization unit" description: key: "error.roleservice.mandated_role_not_in_ou_description" defaultValue: "A sharing policy can only mandate a role in an organization unit that owns the role or has it shared with it" sectionKindChange: summary: An edit that turns a section naming units into one reaching a whole group, or the reverse value: code: "USR-1029" message: key: "error.userservice.invalid_sharing_policy" defaultValue: "Invalid sharing policy" description: key: "error.sharingservice.scope_family_change_description" defaultValue: "A section naming organization units individually cannot become one reaching a whole family, or the reverse; delete the policy and issue the one you want instead" declaredPolicy: summary: An edit aimed at a policy a resource file declares value: code: "USR-1033" message: key: "error.userservice.sharing_policy_declared" defaultValue: "Sharing policy is declared" description: key: "error.userservice.sharing_policy_declared_description" defaultValue: "The sharing policy is declared in a resource file and cannot be changed through the API" UserSharingPolicyDeleteBadRequest: description: | The policy exists but is not this endpoint's to remove. A policy that is simply absent answers 204, because a delete says what the state should be afterwards. content: application/json: schema: $ref: '#/components/schemas/Error' examples: declaredPolicy: summary: A delete aimed at a policy a resource file declares value: code: "USR-1033" message: key: "error.userservice.sharing_policy_declared" defaultValue: "Sharing policy is declared" description: key: "error.userservice.sharing_policy_declared_description" defaultValue: "The sharing policy is declared in a resource file and cannot be changed through the API" UserOverlayRulesBadRequest: description: The request does not say which organization unit to resolve for. content: application/json: schema: $ref: '#/components/schemas/Error' examples: missingOuId: summary: The ouId query parameter is absent or empty value: code: "USR-1035" message: key: "error.userservice.missing_ou_id_parameter" defaultValue: "Missing required parameter" description: key: "error.userservice.missing_ou_id_parameter_description" defaultValue: "The 'ouId' query parameter is required" SharingUserNotFound: description: No such user content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" UserOverlayNotResolvable: description: | No such user, or no sharing policy reaches the organization unit, so the user is not available there and has no terms to resolve. content: application/json: schema: $ref: '#/components/schemas/Error' examples: notShared: summary: An organization unit no policy reaches value: code: "USR-1034" message: key: "error.userservice.user_not_shared_to_ou" defaultValue: "User is not shared to the organization unit" description: key: "error.userservice.user_not_shared_to_ou_description" defaultValue: "No sharing policy reaches the specified organization unit, so the user is not available there" noSuchUser: summary: No such user value: code: "USR-1003" message: key: "error.userservice.user_not_found" defaultValue: "User not found" description: key: "error.userservice.user_not_found_description" defaultValue: "The user with the specified id does not exist" UserSharingPolicyNotFound: description: No such sharing policy on this user content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-1030" message: key: "error.userservice.sharing_policy_not_found" defaultValue: "Sharing policy not found" description: key: "error.userservice.sharing_policy_not_found_description" defaultValue: "The user has no sharing policy with the specified id" UserSharingPolicyConflict: description: | The organization unit already holds a policy for this user, or the policy moved since it was read. content: application/json: schema: $ref: '#/components/schemas/Error' examples: alreadyExists: summary: A second policy for the same organization unit value: code: "USR-1031" message: key: "error.userservice.sharing_policy_exists" defaultValue: "Sharing policy already exists" description: key: "error.userservice.sharing_policy_exists_description" defaultValue: "This organization unit already has a sharing policy for the user; edit it instead" staleVersion: summary: An edit against a stale version value: code: "USR-1032" message: key: "error.userservice.sharing_policy_version_mismatch" defaultValue: "Sharing policy version mismatch" description: key: "error.userservice.sharing_policy_version_mismatch_description" defaultValue: "The sharing policy changed since it was read; read it again and retry the edit" UserSharingServerError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: code: "USR-5000" message: key: "error.internal_server_error" defaultValue: "Internal server error" description: key: "error.internal_server_error_description" defaultValue: "An unexpected error occurred while processing the request" SharingForbidden: description: | The caller may not act for the organization unit the request concerns: the initiating organization unit for a create, edit, or delete, and the user's own unit or the policy's initiating unit for a read. content: application/json: schema: $ref: '#/components/schemas/Error' examples: unauthorized: summary: The caller may not act for the organization unit value: code: "SSE-4030" message: key: "error.unauthorized" defaultValue: "Unauthorized" description: key: "error.unauthorized_description" defaultValue: "The caller is not authorized to perform this operation" grantNotPermitted: summary: A share mandating a role the caller may not grant value: code: "SAZ-4030" message: key: "error.sysauthz.grant_not_permitted" defaultValue: "Insufficient privileges to grant these permissions" description: key: "error.sysauthz.grant_not_permitted_description" defaultValue: "The operation would grant permissions that the caller does not hold" schemas: ResourceUsage: type: object description: A single resource that references the target resource. required: - resourceType - id - displayName - behaviorOnDelete properties: resourceType: type: string description: Type of the referencing resource. enum: [application, agent] example: agent id: type: string format: uuid description: Identifier of the referencing resource. example: "a1b2c3d4-0000-0000-0000-000000000001" displayName: type: string description: Human-readable name of the referencing resource. example: "Support Agent" behaviorOnDelete: type: string description: | What happens to this resource when the target resource is deleted. - `fallback`: the reference is kept as-is. - `cascade`: the resource is permanently deleted. enum: [fallback, cascade] example: fallback ResourceUsagesSummary: type: object nullable: true description: | Per-resource-type count of usages, keyed by resource type (e.g. `agent`). Null when the counts could not be determined. additionalProperties: type: integer example: agent: 2 ResourceUsagesResponse: type: object description: | Resources that reference a target resource, aggregated across all resource types. Drives pre-delete confirmation dialogs; informational only. properties: totalResults: type: integer nullable: true description: | Total number of resources that reference the target resource. Null when usage data is unavailable; 0 means confirmed empty. example: 2 count: type: integer description: Number of results returned. example: 2 summary: $ref: '#/components/schemas/ResourceUsagesSummary' usages: type: array items: $ref: '#/components/schemas/ResourceUsage' User: type: object required: [id] properties: id: type: string format: uuid ouId: type: string format: uuid ouHandle: type: string readOnly: true description: "Human-readable handle of the organization unit (only included when include=display query parameter is used)." type: type: string attributes: type: object additionalProperties: true display: type: string readOnly: true description: "Display name of the user (only included when include=display query parameter is used). Resolved from the schema-configured display attribute (`systemAttributes.display`). Falls back to the user ID if no display attribute is configured, the configured attribute path does not exist in the user's data, or the attribute value is empty." isReadOnly: type: boolean readOnly: true description: "Whether the user is declarative and cannot be modified or deleted by clients." isOwnedByOU: type: boolean readOnly: true description: | Whether the listed organization unit owns the user rather than being shared it. Present only in user lists. status: $ref: '#/components/schemas/UserAccessStatus' lastLoginAt: type: string format: date-time readOnly: true description: | When the user last signed in, including session reuse. Set by the server and never accepted on a write. Absent until recorded. Recording is off for users unless `accountAccess.user.recordLastLogin` is enabled, and the value can lag the latest sign-in by up to `accountAccess.user.lastLoginResolutionSeconds` (one hour by default). Use it to find inactive accounts, not to audit individual sign-ins. example: "2026-09-09T18:22:04Z" UserAccessStatus: type: object readOnly: true description: | The user's effective access status and the reason for it. Computed when the user is read or updated, and never accepted on a write. properties: value: type: string readOnly: true enum: [ACTIVE, LOCKED, SUSPENDED] description: | `ACTIVE`, `LOCKED` or `SUSPENDED`. When the user is both suspended and locked, `SUSPENDED` is reported. `SUSPENDED` is an administrative hold placed by the suspend flow. While suspended, the user cannot authenticate, use existing sessions, get new or refreshed tokens, or recover the account, but the record can still be updated. The unsuspend flow removes the suspension and leaves the user `LOCKED` until self-service recovery or the unlock flow clears the lock. `LOCKED` is a hold after repeated failed sign-ins or after a suspension is released. The suspension release lock does not expire, even when automatic locking is disabled. An automatic lock does not expire when its duration is `0` or it forms at `maxConsecutiveFailures`; other automatic locks expire on their own. Self-service recovery with an unlock step or the administration unlock flow clears a lock earlier. example: "ACTIVE" details: type: object readOnly: true description: | Why the status applies and how it is cleared. Absent for `ACTIVE`. An authentication refusal states only that the account is locked or suspended. The locked methods, expiry times, and operator note are returned only here, to callers allowed to read the user. properties: reason: type: string readOnly: true enum: [FAILED_ATTEMPTS, SUSPENSION_RELEASE_LOCK, ADMINISTRATIVE_SUSPENSION] description: | What caused the status. `FAILED_ATTEMPTS` is an automatic lock after repeated failed sign-ins. `SUSPENSION_RELEASE_LOCK` is the account-wide lock the unsuspend flow leaves, which does not expire. `ADMINISTRATIVE_SUSPENSION` is a suspension placed by an operator. One reason covers every entry in `lockedMethods`. A suspension release lock is never reported together with authentication method locks. example: "FAILED_ATTEMPTS" since: type: string format: date-time readOnly: true description: When the operator placed the hold. Absent for an automatic lock. operatorNote: type: string readOnly: true maxLength: 100 description: | The note the operator entered when placing the hold. Absent when none was entered. Never included in an authentication refusal or in `/users/me` responses. example: "Credential exposure reported by the security team" lockedMethods: type: array readOnly: true description: | The automatic locks currently in force, in a stable order. Absent unless the status is `LOCKED`. With `lockGranularity` set to `authentication_method`, each method locks separately, so several entries can be present, each with its own expiry. An account-wide lock is reported as a single entry with the method `account`. items: type: object properties: method: type: string readOnly: true description: | The locked authentication method, such as `credential`, or `account` when every method is locked. example: "credential" expiresAt: type: string format: date-time readOnly: true description: | When the lock expires. **Absent when it does not expire**: self-service recovery or the unlock flow clears it. example: "2026-09-08T10:15:00Z" AccessibleOrganizationUnit: type: object required: [id, handle, name] properties: id: type: string format: uuid handle: type: string name: type: string logoUrl: type: string format: uri AccessibleOrganizationUnitListResponse: type: object required: [current, totalResults, startIndex, count, organizationUnits, links] properties: current: type: string format: uuid description: The organization unit the list is relative to. totalResults: type: integer description: "Number of results that match the listing operation." startIndex: type: integer description: "Index of the first element of the page, which will be equal to offset + 1." count: type: integer description: "Number of elements in the returned page." organizationUnits: type: array items: $ref: '#/components/schemas/AccessibleOrganizationUnit' links: type: array items: $ref: '#/components/schemas/Link' Link: type: object properties: href: type: string example: "organization-units?offset=20&limit=10" rel: type: string example: "next" UserGroup: type: object required: [id, name, ouId] properties: id: type: string format: uuid description: "The unique identifier of the group" name: type: string description: "The name of the group" ouId: type: string format: uuid description: "The organization unit ID that the group belongs to" UserListResponse: type: object properties: totalResults: type: integer description: "Number of results that match the listing operation." example: 25 startIndex: type: integer description: "Index of the first element of the page, which will be equal to offset + 1." example: 1 count: type: integer description: "Number of elements in the returned page." example: 10 users: type: array items: $ref: '#/components/schemas/User' links: type: array items: $ref: '#/components/schemas/Link' UserGroupListResponse: type: object properties: totalResults: type: integer description: "Number of results that match the listing operation." example: 8 startIndex: type: integer description: "Index of the first element of the page, which will be equal to offset + 1." example: 1 count: type: integer description: "Number of elements in the returned page." example: 5 groups: type: array items: $ref: '#/components/schemas/UserGroup' links: type: array items: $ref: '#/components/schemas/Link' CreateUserByPathRequest: type: object required: [type] properties: type: type: string description: "The handle of the user type" example: "employee" attributes: type: object description: "User attributes" additionalProperties: true example: username: "john.doe" firstname: "John" lastname: "Doe" email: "john.doe@company.com" department: "Engineering" CreateUserRequest: type: object required: [ouId, type] properties: ouId: type: string format: uuid description: "The organization unit ID where the user will be created" type: type: string description: "The handle of the user type" example: "customer" attributes: type: object description: "User attributes" additionalProperties: true UpdateUserRequest: type: object properties: ouId: type: string format: uuid description: "The organization unit ID where the user belongs" type: type: string description: "The handle of the user type" attributes: type: object description: "User attributes" additionalProperties: true UpdateSelfUserRequest: type: object required: [attributes] properties: attributes: type: object description: "User attributes" additionalProperties: true UpdateUserCredentialsRequest: type: object required: [credentials] properties: credentials: type: object description: "Credential key-value pairs to update. Keys must match credential fields defined in the user type schema." additionalProperties: type: string UserType: type: object required: [id, handle, displayName, ouId, schema] properties: id: type: string format: uuid description: "The unique identifier of the user type" handle: type: string description: | Unique handle of the user type (lowercase letters, numbers, hyphens, and underscores only). The handle is unique among user types. Once set, the handle cannot be changed. pattern: '^[a-z0-9][a-z0-9_-]*[a-z0-9]$|^[a-z0-9]$' maxLength: 100 example: "customer" displayName: type: string description: "Human-readable name of the user type. It does not need to be unique and can be changed at any time." minLength: 1 maxLength: 100 example: "Customer" ouId: type: string format: uuid description: "The root organization unit ID associated with this user type schema" ouHandle: type: string readOnly: true description: "Human-readable handle of the organization unit (only included when include=display query parameter is used)." allowSelfRegistration: type: boolean description: "Indicates whether users of this type can perform self-registration flows" default: false systemAttributes: type: object description: "System-level metadata for the user type" properties: display: type: string description: "The schema attribute to use as the human-readable display name for users of this type" primaryEmail: type: string description: "Top-level email attribute used as the primary contact. Defaults to the only top-level email attribute; stays unset when there are several and none is selected. Must reference an email type." primaryMobile: type: string description: "Top-level mobile attribute used as the primary contact. Defaults to the only top-level mobile attribute; stays unset when there are several and none is selected. Must reference a mobile type." additionalProperties: false schema: type: object description: "JSON Schema definition for the user type" additionalProperties: oneOf: - type: object description: "Leaf property - string, email, mobile, or number" required: [type] properties: type: type: string enum: ["string", "email", "mobile", "number"] description: "Data type of the property" required: type: boolean default: false description: "Whether this attribute must be provided for the user type" unique: type: boolean default: false description: "Whether this property must be unique across all users" credential: type: boolean default: false description: "Whether this property should be treated as a credential attribute. Not supported for email or mobile types." enum: type: array items: type: string description: "List of allowed values for this property. Not supported for email or mobile types." regex: type: string description: "Regular expression pattern for validating the property value" additionalProperties: false - type: object description: "Leaf property - boolean" required: [type] properties: type: type: string enum: ["boolean"] description: "Data type of the property" required: type: boolean default: false description: "Whether this attribute must be provided for the user type" additionalProperties: false - type: object description: "Object property definition" required: [type, properties] properties: type: type: string enum: ["object"] description: "Data type (object)" required: type: boolean default: false description: "Whether this attribute must be provided for the user type" properties: type: object description: "Nested properties of the object" additionalProperties: $ref: "#/components/schemas/UserType/properties/schema/additionalProperties" additionalProperties: false - type: object description: "Array property definition" required: [type, items] properties: type: type: string enum: ["array"] description: "Data type (array)" required: type: boolean default: false description: "Whether this attribute must be provided for the user type" items: oneOf: - type: object description: "Array of strings, emails, mobiles, or numbers" required: [type] properties: type: type: string enum: ["string", "email", "mobile", "number"] enum: type: array items: type: string description: "List of allowed values. Not supported for email or mobile types." regex: type: string description: "Custom validation pattern. Contact types use their default when omitted or empty." additionalProperties: false - type: object description: "Array of booleans" required: [type] properties: type: type: string enum: ["boolean"] additionalProperties: false - type: object description: "Array of objects" required: [type, properties] properties: type: type: string enum: ["object"] properties: type: object additionalProperties: $ref: "#/components/schemas/UserType/properties/schema/additionalProperties" additionalProperties: false additionalProperties: false example: email: type: "string" required: true unique: true regex: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" password: type: "string" required: true credential: true regex: "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]).{8,}$" age: type: "number" isActive: type: "boolean" phoneNumber: type: "string" regex: "^\\+?[1-9]\\d{1,14}$" role: type: "string" enum: ["admin", "user", "guest"] address: type: "object" required: true properties: street: type: "string" city: type: "string" required: true zipCode: type: "string" regex: "^\\d{5}(-\\d{4})?$" tags: type: "array" items: type: "string" enum: ["vip", "premium", "standard"] UserTypeListResponse: type: object properties: totalResults: type: integer description: "Number of results that match the listing operation." example: 5 startIndex: type: integer description: "Index of the first element of the page, which will be equal to offset + 1." example: 1 count: type: integer description: "Number of elements in the returned page." example: 3 types: type: array items: type: object required: [id, handle, displayName, ouId] properties: id: type: string format: uuid description: "The unique identifier of the user type" handle: $ref: "#/components/schemas/UserType/properties/handle" displayName: $ref: "#/components/schemas/UserType/properties/displayName" ouId: type: string format: uuid description: "The root organization unit ID associated with this user type schema" ouHandle: type: string readOnly: true description: "Human-readable handle of the organization unit (only included when include=display query parameter is used)." allowSelfRegistration: type: boolean description: "Indicates whether users of this type can perform self-registration flows" default: false systemAttributes: type: object description: "System-level metadata for the user type" properties: display: type: string description: "The schema attribute to use as the human-readable display name for users of this type" primaryEmail: type: string description: "Top-level email attribute used as the primary contact. Defaults to the only top-level email attribute; stays unset when there are several and none is selected. Must reference an email type." primaryMobile: type: string description: "Top-level mobile attribute used as the primary contact. Defaults to the only top-level mobile attribute; stays unset when there are several and none is selected. Must reference a mobile type." additionalProperties: false isReadOnly: type: boolean readOnly: true description: "Indicates whether the user type is defined declaratively and cannot be modified through the API" links: type: array items: $ref: '#/components/schemas/Link' CreateUserTypeRequest: type: object required: [handle, displayName, ouId, schema] properties: handle: type: string description: | Unique handle for the user type (lowercase letters, numbers, hyphens, and underscores only). The handle must be unique among user types. Once set, the handle cannot be changed. pattern: '^[a-z0-9][a-z0-9_-]*[a-z0-9]$|^[a-z0-9]$' maxLength: 100 example: "partner" displayName: type: string description: "Human-readable name of the user type. It does not need to be unique." minLength: 1 maxLength: 100 example: "Partner" ouId: type: string format: uuid description: "The organization unit ID where this user type schema is applicable" allowSelfRegistration: type: boolean description: "Whether the user type supports user-initiated registration" default: false systemAttributes: $ref: "#/components/schemas/UserType/properties/systemAttributes" schema: type: object description: "JSON Schema definition for the user type" additionalProperties: $ref: "#/components/schemas/UserType/properties/schema/additionalProperties" UpdateUserTypeRequest: type: object required: [displayName, ouId, schema] properties: handle: type: string description: | Optional. The handle cannot be changed, so when provided it must match the handle the user type was created with. When omitted, the existing handle is kept. pattern: '^[a-z0-9][a-z0-9_-]*[a-z0-9]$|^[a-z0-9]$' maxLength: 100 example: "customer" displayName: type: string description: "Human-readable name of the user type. It does not need to be unique." minLength: 1 maxLength: 100 example: "Customer" ouId: type: string format: uuid description: "The root organization unit ID where this user type schema is applicable" allowSelfRegistration: type: boolean description: "Whether the user type supports user-initiated registration" default: false systemAttributes: $ref: "#/components/schemas/UserType/properties/systemAttributes" schema: type: object description: "JSON Schema definition for the user type" additionalProperties: $ref: "#/components/schemas/UserType/properties/schema/additionalProperties" UserSharingPolicyRequest: type: object additionalProperties: false description: | One organization unit's decision about this user. A policy states up to two sections through this endpoint, and at least one: `childUnits` for the organization units beneath the issuer, and `otherTreeRoots` for the roots of other trees. Each section either reaches a whole group or names the organization units it reaches, never both. A user shared with nobody has no policy at all. anyOf: - required: [childUnits] - required: [otherTreeRoots] properties: initiatingOuId: type: string description: | The organization unit whose decision this is. Omitted means the user's owner. A unit other than the owner may only issue a policy where the user already reached it and stopped there, and such a policy may state `childUnits` only. example: "acme-root" childUnits: $ref: '#/components/schemas/UserChildUnits' otherTreeRoots: $ref: '#/components/schemas/UserOtherTreeRootsSelected' version: type: integer description: | The policy version the caller believes it is editing. Required on an edit, ignored on a create. example: 1 UserSharingPolicyUpdateRequest: type: object additionalProperties: false required: [version] description: | A replacement for a policy's sections. Whose decision the policy is cannot change, so an edit names no `initiatingOuId`. It is held to the rules of a create, with these differences. Each section keeps its kind. A section that reaches a whole group (`mode: all`, or `allUnits`) stays one: its `excludedOuIds` can be added to or removed from, but the section cannot be dropped or turned into one that names units. That is also how a policy that already reaches every organization unit, or the root of every other tree, keeps that reach here although a create may not state it. A section that names units may add or drop units, change a unit's `reach`, or be removed, but cannot become one that reaches a whole group. An edit cannot reach past an organization unit that has already shared the user on. Widening that unit from `unit` to `subtree` is refused until the policy it issued is removed. anyOf: - required: [allUnits] - required: [childUnits] - required: [otherTreeRoots] properties: allUnits: $ref: '#/components/schemas/UserAllUnits' childUnits: $ref: '#/components/schemas/UserChildUnits' otherTreeRoots: $ref: '#/components/schemas/UserOtherTreeRoots' version: type: integer description: | The policy version the caller believes it is editing. An edit against any other version is refused, so a caller that has not seen the current one cannot overwrite it. example: 1 UserAllUnits: type: object additionalProperties: false description: | Every organization unit in the deployment, at any depth, including units created later. It stands alone: a policy that states it states neither `childUnits` nor `otherTreeRoots`. A reach not bounded by the issuer's own position in the tree is a deployment decision, so it is written where such decisions are reviewed: a resource file, or a document imported from one. A create through this API may not state it. A policy written that way still reads back through these endpoints, and an edit restates it to rewrite its exclusions. properties: excludedOuIds: type: array description: | Organization units withheld from the section, each taking everything beneath it out of reach as well. Any organization unit may be excluded. items: type: string example: ["acme-trial-customers"] UserChildUnits: description: | The organization units beneath the issuer. Exactly one of the two shapes below, chosen by `mode`. oneOf: - $ref: '#/components/schemas/UserChildUnitsAll' - $ref: '#/components/schemas/UserChildUnitsSelected' discriminator: propertyName: mode mapping: all: '#/components/schemas/UserChildUnitsAll' selected: '#/components/schemas/UserChildUnitsSelected' UserChildUnitsAll: type: object additionalProperties: false required: [mode] description: Everything beneath the issuing organization unit, at any depth, including units created later. properties: mode: type: string enum: [all] excludedOuIds: type: array description: | Organization units withheld from the section, each taking everything beneath it out of reach as well. Only organization units directly beneath the issuer may be excluded. items: type: string example: ["acme-trial-customers"] UserChildUnitsSelected: type: object additionalProperties: false required: [mode, units] description: | Named organization units directly beneath the issuer. It takes no `excludedOuIds`: an organization unit is withheld by leaving it out of `units`. properties: mode: type: string enum: [selected] units: type: array minItems: 1 description: The organization units reached. An organization unit is listed only once in a policy. items: $ref: '#/components/schemas/UserChildUnit' UserChildUnit: type: object additionalProperties: false required: [ouId, reach] properties: ouId: type: string description: A direct child of the issuing organization unit. example: "acme-customer-a" reach: type: string enum: [unit, subtree] description: | How far the user carries from the named organization unit. `unit` reaches it and nothing below it, which leaves it free to pass the user on itself. `subtree` reaches it and everything below it at any depth. example: unit overlayRules: $ref: '#/components/schemas/UserOverlayRules' UserOverlayRules: type: object additionalProperties: false description: | The terms the organization unit holds the user on. A user declares one field, `roles`: the roles the share mandates for the user in that organization unit. A rule is accepted only on a unit named under `childUnits` in `selected` mode with `reach: unit`. properties: roles: $ref: '#/components/schemas/UserRolesRule' UserRolesRule: type: object additionalProperties: false required: [editable, value] description: | The roles mandated for the user in the organization unit. Writing the share writes one mandated role assignment for each role, in that organization unit. Updating the share brings the assignments in line with the new list, and deleting the share removes them. The rule is fixed: `editable` is `false` and `value` lists at least one role ID. Each role must be owned by, or shared with, the organization unit, and the caller must be allowed to grant it, by the same check as a direct assignment. A reshare from a mandated unit can carry only roles from its own mandate. properties: editable: type: boolean enum: [false] example: false value: type: array minItems: 1 description: The IDs of the roles to mandate. items: type: string example: ["0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a11"] UserOtherTreeRoots: description: | The root organization units of other trees, as a policy carries them. Every shape a create may send, plus the one that only a resource file or an imported document may introduce. An edit sends this shape rather than the create's, because a policy that already reaches the root of every other tree has to be able to restate that to rewrite its exclusions. oneOf: - $ref: '#/components/schemas/UserOtherTreeRootsSelected' - $ref: '#/components/schemas/UserOtherTreeRootsAll' discriminator: propertyName: mode mapping: selected: '#/components/schemas/UserOtherTreeRootsSelected' all: '#/components/schemas/UserOtherTreeRootsAll' UserOtherTreeRootsSelected: type: object additionalProperties: false required: [mode, units] description: | Named root organization units of other trees, and nothing below them. Owner only. Another tree is reached at its root alone; that root passes the user on within its own tree. The root of the owner's own tree is not another tree and cannot be named. When the owner sits below a root, this additionally requires `resource_sharing.allow_child_ou_cross_tree_sharing`. properties: mode: type: string enum: [selected] units: type: array minItems: 1 description: The root organization units reached. An organization unit is listed only once in a policy. items: $ref: '#/components/schemas/UserRootUnit' UserOtherTreeRootsAll: type: object additionalProperties: false required: [mode] description: | The root organization unit of every other tree, including trees created later. Only a resource file or an imported document may introduce it, so a create never sends it. properties: mode: type: string enum: [all] excludedOuIds: type: array description: Root organization units withheld from the section, and with them their trees. items: type: string example: ["partner-root"] UserRootUnit: type: object additionalProperties: false required: [ouId] properties: ouId: type: string description: The root organization unit of another tree. example: "partner-root" UserSharingPolicy: type: object description: | A recorded sharing policy. Its sections come back in the shape a request states them in, so an edit copies them, with `version`, into a `UserSharingPolicyUpdateRequest`. The other fields are set by the server and are refused in a request body. A section the policy does not state is left out. properties: id: type: string description: The policy's own identifier. example: "0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10" initiatingOuId: type: string description: | The organization unit whose decision this policy is. The owning organization unit is not repeated here: it belongs to the user, which this path already names. example: "acme-root" stage: type: string enum: [share, reshare] description: "`share` when the owner issued it, `reshare` when a sharee did." parentPolicyId: type: string description: The policy that made this one's issuer able to see the user. Empty for an owner-issued policy. isReadOnly: type: boolean readOnly: true description: Indicates if the policy is defined in declarative configuration and cannot be modified. version: type: integer description: Bumped on every edit, and carried back on the next one. example: 1 allUnits: $ref: '#/components/schemas/UserAllUnits' childUnits: $ref: '#/components/schemas/UserChildUnits' otherTreeRoots: $ref: '#/components/schemas/UserOtherTreeRoots' UserSharingPolicyListResponse: type: object properties: totalResults: type: integer description: How many policies the user has, not how many this page holds. example: 2 startIndex: type: integer description: The one-based position of the first policy in this page. example: 1 count: type: integer description: How many policies this page holds. example: 2 policies: type: array items: $ref: '#/components/schemas/UserSharingPolicy' links: type: array description: Links to the first, previous, next and last pages, where they exist. items: $ref: '#/components/schemas/Link' example: - href: "/users/0195a2c0-6f3e-7a21-9f2a-2c4f8f1d9a10/sharing-policies?offset=30&limit=30" rel: "next" UserResolvedOverlay: type: object description: What one organization unit may do with the user. properties: ouId: type: string example: "acme-customer-a" isOwnedByOU: type: boolean description: Whether the organization unit owns the user rather than being shared it. visible: type: boolean description: | Whether the organization unit can see the user at all. This is what decides whether it may be named as the accessing organization unit on a token request. policyIds: type: array description: Every policy that contributed, so an answer is traceable to its inputs. items: type: string rules: type: object description: | The effective rule per templated field: which of the user's fields the organization unit may override, and on what terms. A user declares one field, `roles`, which is present when a user share mandates roles in the organization unit and is otherwise left out, so the map is empty for most organization units. additionalProperties: $ref: '#/components/schemas/UserOverlayRule' UserOverlayRule: type: object description: What a reached organization unit may do with one field. properties: editable: type: boolean value: type: array items: type: string allowedValues: type: array items: type: string excludedValues: type: array items: type: string Error: type: object required: [code, message] properties: code: type: string description: "Error code. Codes follow the USR-XXXX convention." example: "USR-1001" message: $ref: '#/components/schemas/I18nMessage' description: $ref: '#/components/schemas/I18nMessage' I18nMessage: type: object description: Internationalized message with translation key and default value. required: - key - defaultValue properties: key: type: string description: Translation key for fetching localized message. defaultValue: type: string description: Default message in English (fallback).