openapi: 3.0.2
info:
  title: Phase Two Admin REST API
  description: |
    This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html).

    ### Base URI format
    Paths specified in the documentation are relative to the the base URI.
    - Format: `https://<host>:<port>/auth/realms`
    - Example: `https://app.phasetwo.io/auth/realms`

    ### Authentication
    Authentication is achieved by using the `Authentication: Bearer <token>` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint.

    It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires.

    #### Client credentials grant example
    ```
    POST /auth/realms/test-realm/protocol/openid-connect/token
    Host: app.phasetwo.io
    Accept: application/json
    Content-type: application/x-www-form-urlencoded

    grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1
    ```

    #### Password grant example
    ```
    POST /auth/realms/test-realm/protocol/openid-connect/token
    Host: app.phasetwo.io
    Accept: application/json
    Content-type: application/x-www-form-urlencoded

    grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli
    ```

    ### SDKs
    Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml).

    | Language | Library |
    | --- | --- |
    | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java |
    | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js |
    | Python | https://github.com/p2-inc/phasetwo-python |
  version: "v1"
servers:
  - url: "{baseUrl}/realms"
    variables:
      baseUrl:
        default: https://app.phasetwo.io
        description: |
          API base URL without a trailing slash.
          Examples:
          - https://app.phasetwo.io
          - https://app.phasetwo.io/auth
          - http://localhost:8081
          - http://localhost:8081/auth
components:
  securitySchemes:
    access_token:
      type: http
      scheme: bearer
      bearerFormat: ""
  schemas:
    BulkResponseItem:
      type: object
      properties:
        status:
          type: integer
        error:
          type: string
        item:
          type: object
    MyOrganizationsRepresentation:
      type: object
      additionalProperties:
        $ref: "#/components/schemas/MyOrganizationRepresentation"
    MyOrganizationRepresentation:
      type: object
      properties:
        name:
          type: string
        displayName:
          type: string
        url:
          type: string
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
        roles:
          type: array
          items:
            type: string
    IdentityProviderRepresentation:
      type: object
      properties:
        addReadTokenRoleOnCreate:
          type: boolean
        alias:
          type: string
        config:
          type: object
          additionalProperties: true
        displayName:
          type: string
        enabled:
          type: boolean
        firstBrokerLoginFlowAlias:
          type: string
        internalId:
          type: string
        linkOnly:
          type: boolean
        postBrokerLoginFlowAlias:
          type: string
        providerId:
          type: string
        storeToken:
          type: boolean
        trustEmail:
          type: boolean
    IdentityProviderMapperRepresentation:
      type: object
      properties:
        config:
          type: object
          additionalProperties: true
        id:
          type: string
        identityProviderAlias:
          type: string
        identityProviderMapper:
          type: string
        name:
          type: string
    LinkIdentityProviderRepresentation:
      type: object
      properties:
        alias:
          type: string
        post_broker_flow:
          type: string
        sync_mode:
          type: string
    RealmAttributeRepresentation:
      type: object
      properties:
        name:
          type: string
        value:
          type: string
        realm:
          type: string
    KeyedRealmAttributeRepresentation:
      type: object
      additionalProperties:
        $ref: "#/components/schemas/RealmAttributeRepresentation"
    OrganizationRepresentation:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        displayName:
          type: string
        url:
          type: string
        realm:
          type: string
        domains:
          type: array
          items:
            type: string
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    OrganizationConfigRepresentation:
      type: object
      properties:
        createAdminUser:
          type: boolean
          description: Whether to create a default admin user for new organizations
        sharedIdps:
          type: boolean
          description: Whether identity providers can be shared across organizations
        adminEventsEnabled:
          type: boolean
          description: Whether admin events are enabled for organization operations
        eventsEnabled:
          type: boolean
          description: Whether user events are enabled for organization operations
        defaultPostBrokerFlow:
          type: string
          description: Default post broker login flow for organization identity providers
        defaultSyncMode:
          type: string
          description: Default sync mode for organization identity providers
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: Additional configuration attributes
        scimEnabled:
          type: boolean
          description: |
            Realm-level feature flag that turns on per-organization SCIM 2.0
            provisioning. When false (the default) the organization SCIM
            configuration endpoints under `/{realm}/orgs/{orgId}/scim`
            return 404 and the SCIM tab is hidden in the Admin UI.
    OrganizationsExportRepresentation:
      type: object
      properties:
        version:
          type: string
          description: Export format version
        realm:
          type: string
          description: Source realm name
        exportedAt:
          type: string
          format: date-time
          description: Export timestamp
        organizations:
          type: array
          items:
            $ref: "#/components/schemas/OrganizationExportRepresentation"
        config:
          $ref: "#/components/schemas/OrganizationsConfigRepresentation"

    OrganizationExportRepresentation:
      allOf:
        - $ref: "#/components/schemas/OrganizationRepresentation"
        - type: object
          properties:
            roles:
              type: array
              items:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
            identityProviders:
              type: array
              items:
                $ref: "#/components/schemas/IdentityProviderRepresentation"
            members:
              type: array
              items:
                type: object
                properties:
                  userId:
                    type: string
                  email:
                    type: string
                  roles:
                    type: array
                    items:
                      type: string
    OrganizationsImportRepresentation:
      type: object
      properties:
        version:
          type: string
          description: Import format version
        organizations:
          type: array
          items:
            $ref: "#/components/schemas/OrganizationExportRepresentation"
        config:
          $ref: "#/components/schemas/OrganizationsConfigRepresentation"
    OrganizationsImportResultRepresentation:
      type: object
      properties:
        imported:
          type: integer
          description: Number of organizations successfully imported
        updated:
          type: integer
          description: Number of organizations updated
        skipped:
          type: integer
          description: Number of organizations skipped
        errors:
          type: array
          items:
            type: object
            properties:
              organizationName:
                type: string
              error:
                type: string

    OrganizationsConfigRepresentation:
      type: object
      properties:
        createAdminUserEnabled:
          type: boolean
          description: Whether to create a default admin user for new organizations
        sharedIdpsEnabled:
          type: boolean
          description: Whether identity providers can be shared across organizations
    SwitchOrganizationRepresentation:
      type: object
      properties:
        id:
          type: string
          description: The ID of the organization to switch to
      required:
        - id

    AccessTokenResponse:
      type: object
      description: >-
        A freshly issued OIDC token set, reflecting the user's new active
        organization. The `refresh_token` is only present when the client is
        configured to use refresh tokens, and `id_token` only for OIDC requests.
      properties:
        access_token:
          type: string
        expires_in:
          type: integer
          format: int64
        refresh_expires_in:
          type: integer
          format: int64
        refresh_token:
          type: string
        token_type:
          type: string
        id_token:
          type: string
        not-before-policy:
          type: integer
        session_state:
          type: string
        scope:
          type: string

    OrganizationDomainRepresentation:
      type: object
      properties:
        domain_name:
          type: string
        verified:
          type: boolean
        record_key:
          type: string
        record_value:
          type: string
      required:
        - domain_name
        - verified
        - record_key
        - record_value
    OrganizationRoleRepresentation:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
    OrganizationRoleMapRepresentation:
      type: object
      additionalProperties:
        type: array
        items:
          $ref: "#/components/schemas/OrganizationRoleRepresentation"
    OrganizationMemberAttributeRepresentation:
      type: object
      properties:
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    PortalLinkRepresentation:
      type: object
      properties:
        user:
          type: string
        link:
          type: string
        redirect:
          type: string
    InvitationRequestRepresentation:
      type: object
      properties:
        email:
          type: string
        send:
          type: boolean
        inviterId:
          type: string
        redirectUri:
          type: string
        roles:
          type: array
          items:
            type: string
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    InvitationRepresentation:
      type: object
      properties:
        id:
          type: string
        createdAt:
          type: string
        email:
          type: string
        inviterId:
          type: string
        invitationUrl:
          type: string
        organizationId:
          type: string
        roles:
          type: array
          items:
            type: string
        attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    UserRepresentation:
      type: object
      properties:
        attributes:
          type: object
          additionalProperties: true
        createdTimestamp:
          type: integer
          format: int64
        email:
          type: string
        emailVerified:
          type: boolean
        enabled:
          type: boolean
        firstName:
          type: string
        groups:
          type: array
          items:
            type: string
        id:
          type: string
        lastName:
          type: string
        username:
          type: string
    UserBriefRepresentation:
      type: object
      properties:
        createdTimestamp:
          type: integer
          format: int64
        email:
          type: string
        emailVerified:
          type: boolean
        enabled:
          type: boolean
        firstName:
          type: string
        groups:
          type: array
          items:
            type: string
        id:
          type: string
        lastName:
          type: string
        username:
          type: string
    UserWithOrgsRepresentation:
      allOf:
        - $ref: "#/components/schemas/UserRepresentation"
        - type: object
          properties:
            organizations:
              $ref: "#/components/schemas/OrganizationRoleMapRepresentation"
    UserWithOrgsBriefRepresentation:
      allOf:
        - $ref: "#/components/schemas/UserBriefRepresentation"
        - type: object
          properties:
            organizations:
              $ref: "#/components/schemas/OrganizationRoleMapRepresentation"
    AuthDetailsRepresentation:
      type: object
      properties:
        realmId:
          type: string
        clientId:
          type: string
        userId:
          type: string
        ipAddress:
          type: string
        username:
          type: string
        sessionId:
          type: string
    EventRepresentation:
      type: object
      properties:
        id:
          type: string
        uid:
          type: string
        time:
          type: integer
        realmId:
          type: string
        realmName:
          type: string
        organizationId:
          type: string
        type:
          type: string
        representation:
          type: string
        operationType:
          type: string
        resourcePath:
          type: string
        resourceType:
          type: string
        error:
          type: string
        authDetails:
          $ref: "#/components/schemas/AuthDetailsRepresentation"
        details:
          type: object
          additionalProperties: true
    CredentialRepresentation:
      type: object
      properties:
        type:
          type: string
        value:
          type: string
    WebhookRepresentation:
      type: object
      properties:
        attributes:
          type: object
        id:
          type: string
        enabled:
          type: boolean
        url:
          type: string
        secret:
          type: string
        createdBy:
          type: string
        createdAt:
          type: integer
          format: int64
        realm:
          type: string
        eventTypes:
          type: array
          items:
            type: string
    WebhookSendRepresentation:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
        status:
          type: integer
        status_message:
          type: string
        retried:
          type: integer
        sent_at:
          type: string
        event_id:
          type: string
        keycloak_event_type:
          type: string
        keycloak_event_id:
          type: string
        webhook:
          $ref: "#/components/schemas/WebhookRepresentation"
        payload:
          type: string
    OrganizationScimRepresentation:
      type: object
      description: |
        Per-organization SCIM 2.0 service-provider configuration. One of these
        backs the SCIM endpoint at
        `{authServerUrl}/realms/{realm}/scim/v2/organizations/{orgId}/`.
      properties:
        enabled:
          type: boolean
          description: |
            Whether the organization's SCIM endpoint accepts inbound traffic.
            Turn this off to pause provisioning without losing the
            configuration.
        email_as_username:
          type: boolean
          description: |
            When true, the provisioned user's `username` mirrors their
            `email`, and subsequent SCIM update operations do not change
            the username.
        link_idp:
          type: boolean
          description: |
            When true, provisioned users are federated with the
            organization's configured identity provider so they can sign in
            via the org's SSO immediately after provisioning.
        auth:
          $ref: "#/components/schemas/OrganizationScimAuth"
    OrganizationScimAuth:
      type: object
      description: |
        Polymorphic authentication configuration for the inbound SCIM
        endpoint. The `type` field discriminates the variant; the remaining
        fields depend on the variant chosen.
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - KEYCLOAK
            - EXTERNAL_JWT
            - EXTERNAL_SECRET
            - EXTERNAL_BASIC
          description: Authentication mode selector.
      discriminator:
        propertyName: type
        mapping:
          KEYCLOAK: "#/components/schemas/KeycloakScimAuth"
          EXTERNAL_JWT: "#/components/schemas/ExternalJwtScimAuth"
          EXTERNAL_SECRET: "#/components/schemas/ExternalSecretScimAuth"
          EXTERNAL_BASIC: "#/components/schemas/ExternalBasicScimAuth"
      oneOf:
        - $ref: "#/components/schemas/KeycloakScimAuth"
        - $ref: "#/components/schemas/ExternalJwtScimAuth"
        - $ref: "#/components/schemas/ExternalSecretScimAuth"
        - $ref: "#/components/schemas/ExternalBasicScimAuth"
    KeycloakScimAuth:
      type: object
      description: |
        Authenticates inbound SCIM calls with a Keycloak-issued access
        token (Bearer). The caller must hold the realm-management roles
        required to manage members of the organization.
      required:
        - type
      properties:
        type:
          type: string
          enum: [KEYCLOAK]
    ExternalJwtScimAuth:
      type: object
      description: |
        Validates an inbound JWT issued by an external IdP. The token's
        issuer and audience must match the configured values, and the
        signature is verified against keys fetched from the configured
        JWKS URI.
      required:
        - type
      properties:
        type:
          type: string
          enum: [EXTERNAL_JWT]
        issuer:
          type: string
          description: Expected `iss` claim. Must exactly match the upstream IdP's issuer URL.
        audience:
          type: string
          description: Expected `aud` claim.
        jwks_uri:
          type: string
          description: URL the server fetches to validate the JWT signature.
    ExternalSecretScimAuth:
      type: object
      description: |
        Bearer-style shared secret. The client sends
        `Authorization: Bearer <secret>`; the server compares the value
        against a stored Argon2id hash.
      required:
        - type
      properties:
        type:
          type: string
          enum: [EXTERNAL_SECRET]
        shared_secret:
          type: string
          description: |
            Random opaque value. Cleartext on submit; hashed at rest. Omit
            on update to keep the existing secret.
    ExternalBasicScimAuth:
      type: object
      description: |
        HTTP Basic auth. The password is hashed with Argon2id before
        storage.
      required:
        - type
      properties:
        type:
          type: string
          enum: [EXTERNAL_BASIC]
        username:
          type: string
          description: Username for HTTP Basic auth. Stored in cleartext.
        password:
          type: string
          description: |
            Password for HTTP Basic auth. Cleartext on submit; hashed at
            rest. Omit on update to keep the existing password.
    MagicLinkRequest:
      type: object
      properties:
        email:
          type: string
        client_id:
          type: string
        redirect_uri:
          type: string
        username:
          type: string
        expiration_seconds:
          type: integer
        force_create:
          type: boolean
        send_email:
          type: boolean
        update_profile:
          type: boolean
        update_password:
          type: boolean
        scope:
          type: string
        nonce:
          type: string
        state:
          type: string
        code_challenge:
          type: string
        code_challenge_method:
          type: string
        remember_me:
          type: boolean
        reusable:
          type: boolean
        response_mode:
          type: string
      required:
        - client_id
        - redirect_uri
    MagicLinkResponse:
      type: object
      properties:
        user_id:
          type: string
        link:
          type: string
        sent:
          type: boolean
security:
  - access_token: []
externalDocs:
  description: Public documentation
  url: https://phasetwo.io/docs
paths:
  # organization resources
  /{realm}/orgs:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get organizations
      description: Get a paginated list of organizations using optional search query parameters.
      operationId: getOrganizations
      parameters:
        - in: query
          name: search
          schema:
            type: string
          style: form
          description: search by name
        - in: query
          name: first
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: max
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: q
          schema:
            type: string
          style: form
          description: search by attributes using the format (space separated) `k1:v1 k2:v2`
        - in: query
          name: exact
          schema:
            type: string
          style: form
          description: search parameter exact match
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrganizationRepresentation"
    post:
      tags:
        - Organizations
      summary: Create a new organization
      operationId: createOrganization
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationRepresentation"
        required: true
      responses:
        201:
          description: success
          headers:
            Location:
              schema:
                type: string
              description: URI indicating the ID of the new resource.
  /{realm}/orgs/count:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get organizations count
      description: Get a count of organizations using an optional search query.
      operationId: getOrganizationsCount
      parameters:
        - in: query
          name: search
          schema:
            type: string
          style: form
        - in: query
          name: q
          schema:
            type: string
          style: form
          description: search by attributes using the format (space separated) `k1:v1 k2:v2`
        - in: query
          name: exact
          schema:
            type: string
          style: form
          description: exact search
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: integer
                format: int32
  /{realm}/orgs/me:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get orgs and roles for authenticated user
      description: Get a list of all organizations that the user is a member and their roles in those organizations. Similar idea to /userinfo in OIDC.
      operationId: getMe
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MyOrganizationsRepresentation"
  /{realm}/orgs/me/invitations:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get invitations for authenticated user
      description: Get a list of all invitations for the user.
      operationId: invitations
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvitationRepresentation"
  /{realm}/orgs/me/invitations/{invitationId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: invitationId
        description: invitation UUID
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Organizations
      summary: Accept invitation for authenticated user
      description: Accept invitation for authenticated user.
      operationId: acceptInvitation
      responses:
        204:
          description: success
    delete:
      tags:
        - Organizations
      summary: Reject invitation for authenticated user
      description: Reject invitation for authenticated user.
      operationId: rejectInvitation
      responses:
        204:
          description: success
  /{realm}/orgs/export:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Export organizations
      operationId: exportOrganizations
      description: Export all organizations and their configurations from this realm
      parameters:
        - in: query
          name: includeMembers
          schema:
            type: boolean
            default: false
          style: form
          description: Include organization members in the export
        - in: query
          name: includeRoles
          schema:
            type: boolean
            default: true
          style: form
          description: Include organization roles in the export
        - in: query
          name: includeIdps
          schema:
            type: boolean
            default: true
          style: form
          description: Include identity providers in the export
        - in: query
          name: orgIds
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Specific organization IDs to export (if not provided, exports all)
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationsExportRepresentation"
            application/octet-stream:
              schema:
                type: string
                format: binary

  /{realm}/orgs/import:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Organizations
      summary: Import organizations
      operationId: importOrganizations
      description: Import organizations and their configurations into this realm
      parameters:
        - in: query
          name: skipExisting
          schema:
            type: boolean
            default: false
          style: form
          description: Skip organizations that already exist instead of updating them
        - in: query
          name: importMembers
          schema:
            type: boolean
            default: false
          style: form
          description: Import organization members (requires existing users in realm)
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationsImportRepresentation"
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: JSON file containing organizations export
        required: true
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationsImportResultRepresentation"
        400:
          description: Invalid import data or format
        409:
          description: Conflicts with existing organizations
  /{realm}/orgs/{orgId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get organization by id
      operationId: getOrganizationById
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationRepresentation"
    put:
      tags:
        - Organizations
      summary: Update this organization by id
      operationId: updateOrganization
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationRepresentation"
        required: true
      responses:
        204:
          description: success
    delete:
      tags:
        - Organizations
      summary: Delete the organization
      operationId: deleteOrganization
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/portal-link:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Organizations
      summary: Create a link for the organization's IdP Wizard
      operationId: createPortalLink
      description: Create a link for this organization's IdP Wizard. This link encodes an action token on behalf of the organization's default admin user, or the user that is optionally specified in this request. The user specified must be a member of this organization, and have full organization admin roles.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                userId:
                  type: string
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PortalLinkRepresentation"
  /{realm}/orgs/config:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organizations
      summary: Get organization configuration
      operationId: getOrganizationConfig
      description: Get the global organization configuration for this realm
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationConfigRepresentation"
    put:
      tags:
        - Organizations
      summary: Update organization configuration
      operationId: updateOrganizationConfig
      description: Update the global organization configuration for this realm
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationConfigRepresentation"
        required: true
      responses:
        204:
          description: success
        400:
          description: Invalid configuration
  # organization membership resources
  /{realm}/orgs/{orgId}/members:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Memberships
      summary: Get organization memberships
      operationId: getOrganizationMemberships
      description: Get a paginated list of users who are a member of the specified organization.
      parameters:
        - in: query
          name: search
          schema:
            type: string
          style: form
        - in: query
          name: first
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: max
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: excludeAdminAccounts
          schema:
            type: boolean
          style: form
        - in: query
          name: includeOrgs
          schema:
            type: boolean
          style: form
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/UserWithOrgsBriefRepresentation"
  # organization membership resources
  /{realm}/orgs/{orgId}/members/count:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Memberships
      summary: Get organization members count
      operationId: getOrganizationMembershipsCount
      description: Get total number of members of a given organization
      parameters:
        - in: query
          name: excludeAdminAccounts
          schema:
            type: boolean
          style: form
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: integer
                format: int32
  /{realm}/orgs/{orgId}/domains:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization
        - Organization Domains
      summary: Get details for all domains owned by an organization
      operationId: getOrganizationDomains
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrganizationDomainRepresentation"
  /{realm}/orgs/{orgId}/domains/{domainName}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: domainName
        description: domain name
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization
        - Organization Domains
      summary: Get details for a domain owned by an organization
      operationId: getOrganizationDomain
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationDomainRepresentation"
  /{realm}/orgs/{orgId}/domains/{domainName}/verify:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: domainName
        description: domain name
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Organization Domains
      summary: Start domain verification
      operationId: verifyDomain
      description: Initiate a verification check for the domain name owned by this organization
      responses:
        202:
          description: success
  /{realm}/orgs/{orgId}/members/{userId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: userId
        description: user id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Memberships
        - Users
      summary: Check if a user is a member of an organization
      operationId: checkOrganizationMembership
      responses:
        204:
          description: success
    put:
      tags:
        - Organization Memberships
        - Users
      summary: Add an organization member
      operationId: addOrganizationMember
      description: Add the specified user to the specified organization as a member
      responses:
        201:
          description: success
    delete:
      tags:
        - Organization Memberships
      summary: Remove an organization member
      operationId: removeOrganizationMember
      description: Remove the specified user from the specified organization as a member
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/members/{userId}/attributes:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: userId
        description: user id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Memberships
      summary: Get organization member attributes
      operationId: getOrganizationMemberAttributes
      description: Get attributes for a specific member of an organization
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
        400:
          description: User is not a member of the organization
        404:
          description: User doesn't exist
    put:
      tags:
        - Organization Memberships
      summary: Add/update organization member attributes
      operationId: addOrganizationMemberAttributes
      description: Add or update attributes for a specific member of an organization
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationMemberAttributeRepresentation"
        required: true
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
        400:
          description: User is not a member of the organization
        404:
          description: User doesn't exist
  # organization invitation resources
  /{realm}/orgs/{orgId}/invitations:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Organization Invitation
      summary: Create an invitation to an organization
      description: Create an invitation to join the specified organization. Requires a user to register with the application (if they don't already have an account) before they can accept the invitation. Acceptance happens during login via a required action.
      operationId: addOrganizationInvitation
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvitationRequestRepresentation"
        required: true
      responses:
        201:
          description: success
        409:
          description: invitation already exists
    get:
      tags:
        - Organization Invitation
      summary: Get organization invitations
      operationId: getOrganizationInvitations
      description: Get a paginated list of invitations to an organization, using an optional search query for email address.
      parameters:
        - in: query
          name: search
          schema:
            type: string
          style: form
        - in: query
          name: first
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: max
          schema:
            type: integer
            format: int32
          style: form
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/InvitationRepresentation"
  # invitation methods
  /{realm}/orgs/{orgId}/invitations/count:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Invitation
      summary: Get organization invitation count
      operationId: getOrganizationInvitationCount
      description: Get a count of invitations to an organization
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: integer
                format: int32
  /{realm}/orgs/{orgId}/invitations/{invitationId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: invitationId
        description: invitation id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Invitation
      summary: Get organization invitation by ID
      operationId: getOrganizationInvitationById
      description: Get an invitation to an organization by its uuid.
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvitationRepresentation"
    delete:
      tags:
        - Organization Invitation
      summary: Remove a pending invitation
      operationId: removeOrganizationInvitation
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/invitations/{invitationId}/resend-email:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: invitationId
        description: invitation id
        required: true
        schema:
          type: string
        style: simple
    put:
      tags:
        - Organization Invitation
      summary: Resend an Organization Invitation
      operationId: resendOrganizationInvitation
      description: Resend the email for an existing Organization Invitation
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/roles:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Roles
      summary: Get roles for this organization
      operationId: getOrganizationRoles
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrganizationRoleRepresentation"
    post:
      tags:
        - Organization Roles
      summary: Create a new role for this organization
      operationId: createOrganizationRole
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        201:
          description: success
    put:
      tags:
        - Organization Roles
      summary: Create new roles for this organization
      operationId: createOrganizationRoles
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        207:
          description: Multi Status
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BulkResponseItem"
    patch:
      tags:
        - Organization Roles
      summary: Delete this organization roles
      operationId: deleteOrganizationRoles
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        207:
          description: Multi Status
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BulkResponseItem"

  /{realm}/orgs/{orgId}/roles/{name}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: name
        description: organization role name
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Roles
      summary: Get role for this organization by name
      operationId: getOrganizationRole
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
    put:
      tags:
        - Organization Roles
      summary: Update role for this organization
      operationId: updateOrganizationRole
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        204:
          description: success
    delete:
      tags:
        - Organization Roles
      summary: Delete this organization role
      operationId: deleteOrganizationRole
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/roles/{name}/users:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: name
        description: organization role name
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Roles
      summary: Get users with this organization role
      operationId: getUserOrganizationRoles
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/UserRepresentation"
  /{realm}/orgs/{orgId}/roles/{name}/users/{userId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: name
        description: organization role name
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: userId
        description: user id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization Roles
        - Users
      summary: Check if a user has an organization role
      operationId: checkUserOrganizationRole
      responses:
        204:
          description: success
    put:
      tags:
        - Organization Roles
        - Users
      summary: Grant a user an organization role
      operationId: grantUserOrganizationRole
      description: Grant the specified user to the specified organization role
      responses:
        201:
          description: success
    delete:
      tags:
        - Organization Roles
        - Users
      summary: Revoke an organization role from a user
      operationId: revokeUserOrganizationRole
      description: Revoke the specified organization role from the specified user
      responses:
        204:
          description: success
  # identity provider resources
  /{realm}/orgs/{orgId}/idps/import-config:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Identity Providers
      summary: Import identity provider from uploaded JSON file
      operationId: importIdpJson
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /{realm}/orgs/{orgId}/idps:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Identity Providers
      summary: Get identity providers for this organization
      operationId: getIdps
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/IdentityProviderRepresentation"
    post:
      tags:
        - Identity Providers
      summary: Create a new identity provider for this organization
      operationId: createIdp
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdentityProviderRepresentation"
        required: true
      responses:
        201:
          description: success
  /{realm}/orgs/{orgId}/idps/link:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Identity Providers
      summary: Link an existing identity provider to this organization
      operationId: linkIdp
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LinkIdentityProviderRepresentation"
        required: true
      responses:
        201:
          description: success
  /{realm}/orgs/{orgId}/idps/{alias}/unlink:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: alias
        description: idp alias
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Identity Providers
      summary: Unlink an existing and linked identity provider from this organization
      operationId: unlinkIdp
      responses:
        204:
          description: success
  /{realm}/orgs/{orgId}/idps/{alias}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: alias
        description: Identity Provider alias
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Identity Providers
      summary: Get identity provider for this organization by alias
      operationId: getIdp
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdentityProviderRepresentation"
    put:
      tags:
        - Identity Providers
      summary: Update identity provider for this organization by alias
      operationId: updateIdp
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdentityProviderRepresentation"
        required: true
      responses:
        204:
          description: success
    delete:
      tags:
        - Identity Providers
      summary: Delete the identity provider
      operationId: deleteIdp
      responses:
        204:
          description: success
  # identity provider mapper resources
  /{realm}/orgs/{orgId}/idps/{alias}/mappers:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: alias
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Identity Providers
      summary: Get mappers for identity provider
      operationId: getIdpMappers
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/IdentityProviderMapperRepresentation"
    post:
      tags:
        - Identity Providers
      summary: Add a mapper to identity provider
      operationId: addIdpMapper
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdentityProviderMapperRepresentation"
        required: true
      responses:
        201:
          description: success
  /{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: alias
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: id
        description: Mapper id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Identity Providers
      summary: Get mapper by id for the identity provider
      operationId: getIdpMapper
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdentityProviderMapperRepresentation"
    put:
      tags:
        - Identity Providers
      summary: Update a mapper for the identity provider
      operationId: updateIdpMapper
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IdentityProviderMapperRepresentation"
        required: true
      responses:
        200:
          description: success
    delete:
      tags:
        - Identity Providers
      summary: Delete a mapper for the identity provider
      operationId: deleteIdpMapper
      responses:
        204:
          description: success
  # organization SCIM provisioning resources (experimental)
  /{realm}/orgs/{orgId}/scim:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Organization SCIM
      summary: Get the SCIM configuration for an organization
      operationId: getOrganizationScimConfig
      description: |
        Returns the SCIM 2.0 service-provider configuration for the
        organization. Requires `view-organizations` or
        `view-identity-providers` on the organization. Returns 404 if
        the realm-level SCIM flag (`scimEnabled` in the orgs config) is
        off, or if no configuration exists for the organization yet.
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationScimRepresentation"
        401:
          description: Insufficient permission
        404:
          description: SCIM disabled at realm level, or no configuration exists for this organization
    post:
      tags:
        - Organization SCIM
      summary: Create the SCIM configuration for an organization
      operationId: createOrganizationScimConfig
      description: |
        Creates the SCIM 2.0 service-provider configuration for the
        organization. Requires `manage-organizations` or
        `manage-identity-providers` on the organization. Returns 404 if
        the realm-level SCIM flag is off, and 409 if a configuration
        already exists for the organization. Cleartext secrets and basic
        passwords submitted here are hashed with Argon2id before
        persistence.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationScimRepresentation"
        required: true
      responses:
        201:
          description: SCIM configuration created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationScimRepresentation"
        401:
          description: Insufficient permission
        404:
          description: SCIM disabled at realm level
        409:
          description: SCIM configuration already exists for this organization
    put:
      tags:
        - Organization SCIM
      summary: Update the SCIM configuration for an organization
      operationId: updateOrganizationScimConfig
      description: |
        Updates the SCIM 2.0 service-provider configuration for the
        organization. Requires `manage-organizations` or
        `manage-identity-providers` on the organization. Omit
        secret/password fields on `auth` to preserve the existing stored
        credential; supply a new value to rotate.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrganizationScimRepresentation"
        required: true
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationScimRepresentation"
        401:
          description: Insufficient permission
        404:
          description: SCIM disabled at realm level, or no configuration exists for this organization
    delete:
      tags:
        - Organization SCIM
      summary: Delete the SCIM configuration for an organization
      operationId: deleteOrganizationScimConfig
      description: |
        Removes the SCIM 2.0 service-provider configuration for the
        organization. Requires `manage-organizations` or
        `manage-identity-providers` on the organization.
      responses:
        204:
          description: SCIM configuration deleted
        401:
          description: Insufficient permission
        404:
          description: SCIM disabled at realm level, or no configuration exists for this organization
  /{realm}/users/{userId}/orgs:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: userId
        description: user id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Users
      summary: List organizations for the given user
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrganizationRepresentation"
  /{realm}/users/{userId}/orgs/{orgId}/roles:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: userId
        description: user id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: orgId
        description: organization id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Users
        - Organization Roles
      summary: List organization roles for the given user and org
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrganizationRoleRepresentation"
    put:
      tags:
        - Users
        - Organization Roles
      summary: Grant a user organization roles
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        207:
          description: Multi Status
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BulkResponseItem"
    patch:
      tags:
        - Users
        - Organization Roles
      summary: Revoke organization roles from a user
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/OrganizationRoleRepresentation"
        required: true
      responses:
        207:
          description: Multi Status
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/BulkResponseItem"
  /{realm}/users/switch-organization:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    put:
      tags:
        - Users
      summary: Switch active organization for authenticated user
      operationId: switchActiveOrganization
      description: Switch the active organization context for the authenticated user
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SwitchOrganizationRepresentation"
        required: true
      responses:
        200:
          description: >-
            Active organization switched successfully. Returns a new token set
            reflecting the updated active organization; clients should replace
            their stored tokens with these.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccessTokenResponse"
        400:
          description: Malformed request body
        401:
          description: User is not a member of this organization
        404:
          description: Organization not found

  /{realm}/users/active-organization:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Users
      summary: Get active organization for authenticated user
      operationId: getActiveOrganization
      description: Get the currently active organization for the authenticated user
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrganizationRepresentation"
        204:
          description: No active organization set
  /{realm}/events:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Events
      summary: Create a new audit log event
      operationId: createEvent
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EventRepresentation"
        required: true
      responses:
        202:
          description: Event received
        400:
          description: Malformed event
        403:
          description: Rate limit exceeded
        409:
          description: Reserved event type
  /{realm}/attributes:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Attributes
      summary: Get realm attributes
      description: Get a list of attributes for this realm
      operationId: getRealmAttributes
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/KeyedRealmAttributeRepresentation"
    post:
      tags:
        - Attributes
      summary: Create a new realm attribute
      operationId: createRealmAttribute
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RealmAttributeRepresentation"
        required: true
      responses:
        201:
          description: Attribute created
        400:
          description: Malformed attribute
  /{realm}/attributes/{attributeKey}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: attributeKey
        description: attribute key
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Attributes
      summary: Get realm attribute by key
      operationId: getRealmAttributeByKey
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RealmAttributeRepresentation"
        404:
          description: Realm attribute doesn't exist
    put:
      tags:
        - Attributes
      summary: Update realm attribute by key
      operationId: updateRealmAttributeByKey
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RealmAttributeRepresentation"
        required: true
      responses:
        204:
          description: success
        404:
          description: Realm attribute doesn't exist
    delete:
      tags:
        - Attributes
      summary: Delete the realm attribute
      operationId: deleteRealmAttribute
      responses:
        204:
          description: success
        404:
          description: Realm attribute doesn't exist
  /{realm}/webhooks:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhooks
      description: Get a list of webhooks for this realm
      operationId: getWebhooks
      parameters:
        - in: query
          name: first
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: max
          schema:
            type: integer
            format: int32
          style: form
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookRepresentation"
    post:
      tags:
        - Events
      summary: Create a new webhook
      operationId: createWebhook
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookRepresentation"
        required: true
      responses:
        201:
          description: Webhook created
        400:
          description: Malformed webhook
  /{realm}/webhooks/count:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhooks count
      description: Get a count of webhooks.
      operationId: getWebhooksCount
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: integer
                format: int32
  /{realm}/webhooks/{webhookId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: webhookId
        description: webhook id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhook by id
      operationId: getWebhookById
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookRepresentation"
        404:
          description: Webhook doesn't exist
    put:
      tags:
        - Events
      summary: Update this webhook by id
      operationId: updateWebhook
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookRepresentation"
        required: true
      responses:
        204:
          description: success
        404:
          description: Webhook doesn't exist
    delete:
      tags:
        - Events
      summary: Delete the webhook
      operationId: deleteWebhook
      responses:
        204:
          description: success
        404:
          description: Webhook doesn't exist
  /{realm}/webhooks/{webhookId}/secret:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: webhookId
        description: webhook id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhook secret by id
      operationId: getWebhookSecretById
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CredentialRepresentation"
        404:
          description: Webhook doesn't exist
  /{realm}/webhooks/{webhookId}/sends:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: webhookId
        description: webhook id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhook sends
      operationId: getWebhookSends
      parameters:
        - in: query
          name: first
          schema:
            type: integer
            format: int32
          style: form
        - in: query
          name: max
          schema:
            type: integer
            format: int32
          style: form
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookSendRepresentation"
        404:
          description: Webhook doesn't exist
  /{realm}/webhooks/{webhookId}/sends/{sendId}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: webhookId
        description: webhook id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: sendId
        description: send id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get webhook send by id
      operationId: getWebhookSendById
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookSendRepresentation"
        404:
          description: Webhook or send doesn't exist
  /{realm}/webhooks/{webhookId}/sends/{sendId}/resend:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: webhookId
        description: webhook id
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: sendId
        description: send id
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Events
      summary: Resend a webhook by send ID
      operationId: resendWebhookById
      responses:
        202:
          description: success
  /{realm}/webhooks/payload/{type}/{kid}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: type
        description: keycloak event type
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: kid
        description: keycloak event id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get a payload by Keycloak type and id
      operationId: getPayloadByKeycloakTypeAndId
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EventRepresentation"
  /{realm}/webhooks/sends/{type}/{kid}:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: type
        description: keycloak event type
        required: true
        schema:
          type: string
        style: simple
      - in: path
        name: kid
        description: keycloak event id
        required: true
        schema:
          type: string
        style: simple
    get:
      tags:
        - Events
      summary: Get all webhook sends triggered by a Keycloak event
      operationId: getWebhookSendsByKeycloakTypeAndId
      responses:
        200:
          description: success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WebhookSendRepresentation"
  /{realm}/magic-link:
    parameters:
      - in: path
        name: realm
        description: realm name (not id!)
        required: true
        schema:
          type: string
        style: simple
    post:
      tags:
        - Users
      summary: Create a magic link to log in a user
      operationId: createMagicLink
      requestBody:
        description: JSON body
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MagicLinkRequest"
        required: true
      responses:
        200:
          description: Magic Link created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MagicLinkResponse"
        400:
          description: Malformed request
        404:
          description: User or Client not found
