components:
  headers:
    ETag:
      description: エンティティタグ。単体 GET / PATCH レスポンスに付与され、If-Match による条件付き更新に使う (design.md §26.3)。
      schema:
        maxLength: 512
        minLength: 1
        type: string
    X-Request-Id:
      description: リクエストID。成功・エラーを問わず全レスポンスに付与される (design.md §26.3)。
      schema:
        pattern: ^req_[a-z2-7]{32}$
        type: string
  parameters:
    Cursor:
      description: カーソルページネーションの次ページカーソル (design.md §26.3)。
      in: query
      name: cursor
      required: false
      schema:
        maxLength: 2048
        minLength: 1
        type: string
    IdempotencyKey:
      description: 冪等キー。write API (POST/PATCH/DELETE) で指定でき、同一キーの再送は最初の結果を再生する (design.md §26.3)。
      in: header
      name: Idempotency-Key
      required: false
      schema:
        maxLength: 255
        minLength: 1
        type: string
    IfMatch:
      description: 条件付き更新・削除のための ETag (design.md §26.3)。GET/PATCH レスポンスの ETag ヘッダと対になる。
      in: header
      name: If-Match
      required: false
      schema:
        maxLength: 512
        minLength: 1
        type: string
    Limit:
      description: 1ページの取得件数。最大 100 (design.md §26.3)。
      in: query
      name: limit
      required: false
      schema:
        default: 25
        maximum: 100
        minimum: 1
        type: integer
  responses:
    BadRequest:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: リクエスト不正。入力検証エラー等 (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    Conflict:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 競合。slug の UNIQUE 違反や冪等キー衝突、状態遷移の矛盾等 (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    DefaultError:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 上記以外の予期しないエラー (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    Forbidden:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 権限不足。必要な scope を持たない (design.md §26.1 scope最小化、Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    Gone:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 対象リソースは存在したが、有効期限切れで利用できない (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    InternalServerError:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: サーバ内部エラー (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    NotFound:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 対象リソースが存在しない (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    PreconditionFailed:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: If-Match の ETag が現在値と一致しない (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    TooManyRequests:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: レート制限超過 (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
    Unauthorized:
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/ProblemDetails"
      description: 認証エラー。Management API key (`sk_live_...`) または Dashboard session が無効 (Problem Details)。
      headers:
        X-Request-Id:
          $ref: "#/components/headers/X-Request-Id"
  schemas:
    AuditEventListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              action:
                minLength: 1
                type: string
              actor_id:
                anyOf:
                  - minLength: 1
                    type: string
                  - type: "null"
              actor_type:
                enum:
                  - end_user
                  - workspace_member
                  - api_key
                  - system
                type: string
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              id:
                pattern: ^evt_[a-z2-7]{32}$
                type: string
              metadata:
                additionalProperties: {}
                propertyNames:
                  type: string
                type: object
              request_id:
                pattern: ^req_[a-z2-7]{32}$
                type: string
              result:
                enum:
                  - success
                  - failure
                type: string
              subject_id:
                anyOf:
                  - minLength: 1
                    type: string
                  - type: "null"
              subject_type:
                minLength: 1
                type: string
              workspace_id:
                pattern: ^wsp_[a-z2-7]{32}$
                type: string
            required:
              - id
              - environment_id
              - workspace_id
              - actor_type
              - actor_id
              - action
              - subject_type
              - subject_id
              - result
              - request_id
              - metadata
              - created_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    BillingCheckoutSessionCreateRequest:
      additionalProperties: false
      properties:
        cancel_url:
          format: uri
          type: string
        success_url:
          format: uri
          type: string
      required:
        - success_url
        - cancel_url
      type: object
    BillingCheckoutSessionCreateResponse:
      additionalProperties: false
      properties:
        checkout_url:
          format: uri
          type: string
        expires_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - checkout_url
        - expires_at
      type: object
    BillingPortalSessionCreateRequest:
      additionalProperties: false
      properties:
        return_url:
          format: uri
          type: string
      required:
        - return_url
      type: object
    BillingPortalSessionCreateResponse:
      additionalProperties: false
      properties:
        portal_url:
          format: uri
          type: string
      required:
        - portal_url
      type: object
    Client:
      additionalProperties: false
      properties:
        allowed_origins:
          items:
            pattern: ^https?:\/\/[^/?#]+$
            type: string
          maxItems: 50
          type: array
        allowed_resources:
          items:
            format: uri
            type: string
          maxItems: 20
          type: array
        allowed_scopes:
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 50
          type: array
        client_type:
          enum:
            - web_bff
            - web_spa
            - react_native
          type: string
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        id:
          pattern: ^cli_[a-z2-7]{32}$
          type: string
        mobile_app:
          anyOf:
            - additionalProperties: false
              properties:
                android_package_name:
                  anyOf:
                    - pattern: ^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$
                      type: string
                    - type: "null"
                android_sha256_fingerprints:
                  items:
                    pattern: ^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$
                    type: string
                  type: array
                app_scheme:
                  minLength: 1
                  type: string
                ios_bundle_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                ios_team_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                universal_link_host:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
              required:
                - app_scheme
                - ios_bundle_id
                - ios_team_id
                - android_package_name
                - android_sha256_fingerprints
                - universal_link_host
              type: object
            - type: "null"
        name:
          maxLength: 200
          minLength: 1
          type: string
        post_logout_redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        public_key_prefix:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
        redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        require_pkce:
          type: boolean
        status:
          enum:
            - active
            - disabled
          type: string
        token_endpoint_auth_method:
          enum:
            - none
            - client_secret_basic
            - client_secret_post
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - client_type
        - name
        - public_key_prefix
        - redirect_uris
        - post_logout_redirect_uris
        - allowed_origins
        - allowed_scopes
        - allowed_resources
        - token_endpoint_auth_method
        - require_pkce
        - status
        - mobile_app
        - created_at
        - updated_at
      type: object
    ClientCreateRequest:
      additionalProperties: false
      properties:
        allowed_origins:
          default: []
          items:
            pattern: ^https?:\/\/[^/?#]+$
            type: string
          maxItems: 50
          type: array
        allowed_resources:
          default: []
          items:
            format: uri
            type: string
          maxItems: 20
          type: array
        allowed_scopes:
          default: []
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 50
          type: array
        client_type:
          enum:
            - web_bff
            - web_spa
            - react_native
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        mobile_app:
          additionalProperties: false
          properties:
            android_package_name:
              anyOf:
                - pattern: ^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$
                  type: string
                - type: "null"
            android_sha256_fingerprints:
              items:
                pattern: ^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$
                type: string
              type: array
            app_scheme:
              minLength: 1
              type: string
            ios_bundle_id:
              anyOf:
                - minLength: 1
                  type: string
                - type: "null"
            ios_team_id:
              anyOf:
                - minLength: 1
                  type: string
                - type: "null"
            universal_link_host:
              anyOf:
                - minLength: 1
                  type: string
                - type: "null"
          required:
            - app_scheme
            - ios_bundle_id
            - ios_team_id
            - android_package_name
            - android_sha256_fingerprints
            - universal_link_host
          type: object
        name:
          maxLength: 200
          minLength: 1
          type: string
        post_logout_redirect_uris:
          default: []
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        redirect_uris:
          default: []
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        require_pkce:
          default: true
          type: boolean
        token_endpoint_auth_method:
          enum:
            - none
            - client_secret_basic
            - client_secret_post
          type: string
      required:
        - environment_id
        - client_type
        - name
        - token_endpoint_auth_method
      type: object
    ClientCreateResponse:
      additionalProperties: false
      properties:
        allowed_origins:
          items:
            pattern: ^https?:\/\/[^/?#]+$
            type: string
          maxItems: 50
          type: array
        allowed_resources:
          items:
            format: uri
            type: string
          maxItems: 20
          type: array
        allowed_scopes:
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 50
          type: array
        client_secret:
          minLength: 1
          type: string
        client_type:
          enum:
            - web_bff
            - web_spa
            - react_native
          type: string
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        id:
          pattern: ^cli_[a-z2-7]{32}$
          type: string
        mobile_app:
          anyOf:
            - additionalProperties: false
              properties:
                android_package_name:
                  anyOf:
                    - pattern: ^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$
                      type: string
                    - type: "null"
                android_sha256_fingerprints:
                  items:
                    pattern: ^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$
                    type: string
                  type: array
                app_scheme:
                  minLength: 1
                  type: string
                ios_bundle_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                ios_team_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                universal_link_host:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
              required:
                - app_scheme
                - ios_bundle_id
                - ios_team_id
                - android_package_name
                - android_sha256_fingerprints
                - universal_link_host
              type: object
            - type: "null"
        name:
          maxLength: 200
          minLength: 1
          type: string
        post_logout_redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        public_key_prefix:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
        redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        require_pkce:
          type: boolean
        status:
          enum:
            - active
            - disabled
          type: string
        token_endpoint_auth_method:
          enum:
            - none
            - client_secret_basic
            - client_secret_post
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - client_type
        - name
        - public_key_prefix
        - redirect_uris
        - post_logout_redirect_uris
        - allowed_origins
        - allowed_scopes
        - allowed_resources
        - token_endpoint_auth_method
        - require_pkce
        - status
        - mobile_app
        - created_at
        - updated_at
      type: object
    ClientDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        id:
          pattern: ^cli_[a-z2-7]{32}$
          type: string
      required:
        - id
        - deleted
      type: object
    ClientListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              allowed_origins:
                items:
                  pattern: ^https?:\/\/[^/?#]+$
                  type: string
                maxItems: 50
                type: array
              allowed_resources:
                items:
                  format: uri
                  type: string
                maxItems: 20
                type: array
              allowed_scopes:
                items:
                  maxLength: 100
                  minLength: 1
                  pattern: ^\S+$
                  type: string
                maxItems: 50
                type: array
              client_type:
                enum:
                  - web_bff
                  - web_spa
                  - react_native
                type: string
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              id:
                pattern: ^cli_[a-z2-7]{32}$
                type: string
              mobile_app:
                anyOf:
                  - additionalProperties: false
                    properties:
                      android_package_name:
                        anyOf:
                          - pattern: ^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$
                            type: string
                          - type: "null"
                      android_sha256_fingerprints:
                        items:
                          pattern: ^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$
                          type: string
                        type: array
                      app_scheme:
                        minLength: 1
                        type: string
                      ios_bundle_id:
                        anyOf:
                          - minLength: 1
                            type: string
                          - type: "null"
                      ios_team_id:
                        anyOf:
                          - minLength: 1
                            type: string
                          - type: "null"
                      universal_link_host:
                        anyOf:
                          - minLength: 1
                            type: string
                          - type: "null"
                    required:
                      - app_scheme
                      - ios_bundle_id
                      - ios_team_id
                      - android_package_name
                      - android_sha256_fingerprints
                      - universal_link_host
                    type: object
                  - type: "null"
              name:
                maxLength: 200
                minLength: 1
                type: string
              post_logout_redirect_uris:
                items:
                  maxLength: 2048
                  minLength: 1
                  type: string
                maxItems: 50
                type: array
              public_key_prefix:
                anyOf:
                  - minLength: 1
                    type: string
                  - type: "null"
              redirect_uris:
                items:
                  maxLength: 2048
                  minLength: 1
                  type: string
                maxItems: 50
                type: array
              require_pkce:
                type: boolean
              status:
                enum:
                  - active
                  - disabled
                type: string
              token_endpoint_auth_method:
                enum:
                  - none
                  - client_secret_basic
                  - client_secret_post
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - id
              - environment_id
              - client_type
              - name
              - public_key_prefix
              - redirect_uris
              - post_logout_redirect_uris
              - allowed_origins
              - allowed_scopes
              - allowed_resources
              - token_endpoint_auth_method
              - require_pkce
              - status
              - mobile_app
              - created_at
              - updated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    ClientRotateSecretResponse:
      additionalProperties: false
      properties:
        client_secret:
          minLength: 1
          type: string
        id:
          pattern: ^cli_[a-z2-7]{32}$
          type: string
        rotated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - client_secret
        - rotated_at
      type: object
    ClientUpdateRequest:
      additionalProperties: false
      properties:
        allowed_origins:
          items:
            pattern: ^https?:\/\/[^/?#]+$
            type: string
          maxItems: 50
          type: array
        allowed_resources:
          items:
            format: uri
            type: string
          maxItems: 20
          type: array
        allowed_scopes:
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 50
          type: array
        mobile_app:
          anyOf:
            - additionalProperties: false
              properties:
                android_package_name:
                  anyOf:
                    - pattern: ^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$
                      type: string
                    - type: "null"
                android_sha256_fingerprints:
                  items:
                    pattern: ^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$
                    type: string
                  type: array
                app_scheme:
                  minLength: 1
                  type: string
                ios_bundle_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                ios_team_id:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
                universal_link_host:
                  anyOf:
                    - minLength: 1
                      type: string
                    - type: "null"
              required:
                - app_scheme
                - ios_bundle_id
                - ios_team_id
                - android_package_name
                - android_sha256_fingerprints
                - universal_link_host
              type: object
            - type: "null"
        name:
          maxLength: 200
          minLength: 1
          type: string
        post_logout_redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        redirect_uris:
          items:
            maxLength: 2048
            minLength: 1
            type: string
          maxItems: 50
          type: array
        require_pkce:
          type: boolean
        status:
          enum:
            - active
            - disabled
          type: string
        token_endpoint_auth_method:
          enum:
            - none
            - client_secret_basic
            - client_secret_post
          type: string
      type: object
    Connection:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        id:
          pattern: ^con_[a-z2-7]{32}$
          type: string
        issuer:
          anyOf:
            - format: uri
              type: string
            - type: "null"
        mode:
          enum:
            - managed
            - byo
          type: string
        owner_confirmed:
          type: boolean
        profile_mapping:
          additionalProperties:
            type: string
          propertyNames:
            type: string
          type: object
        provider:
          enum:
            - google
            - apple
            - github
            - microsoft
            - generic_oidc
          type: string
        provider_client_id:
          minLength: 1
          type: string
        provider_key:
          maxLength: 100
          minLength: 1
          pattern: ^[a-z0-9]+(?:[_-][a-z0-9]+)*$
          type: string
        scopes:
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 20
          type: array
        status:
          enum:
            - active
            - disabled
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - provider
        - mode
        - provider_key
        - issuer
        - provider_client_id
        - scopes
        - profile_mapping
        - status
        - owner_confirmed
        - created_at
        - updated_at
      type: object
    ConnectionCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        issuer:
          format: uri
          type: string
        mode:
          enum:
            - managed
            - byo
          type: string
        profile_mapping:
          additionalProperties:
            type: string
          default: {}
          propertyNames:
            type: string
          type: object
        provider:
          enum:
            - google
            - apple
            - github
            - microsoft
            - generic_oidc
          type: string
        provider_client_id:
          minLength: 1
          type: string
        provider_client_secret:
          minLength: 1
          type: string
        provider_key:
          maxLength: 100
          minLength: 1
          pattern: ^[a-z0-9]+(?:[_-][a-z0-9]+)*$
          type: string
        scopes:
          default: []
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 20
          type: array
      required:
        - environment_id
        - provider
        - mode
        - provider_key
        - provider_client_id
        - provider_client_secret
      type: object
    ConnectionDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        id:
          pattern: ^con_[a-z2-7]{32}$
          type: string
      required:
        - id
        - deleted
      type: object
    ConnectionListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              id:
                pattern: ^con_[a-z2-7]{32}$
                type: string
              issuer:
                anyOf:
                  - format: uri
                    type: string
                  - type: "null"
              mode:
                enum:
                  - managed
                  - byo
                type: string
              owner_confirmed:
                type: boolean
              profile_mapping:
                additionalProperties:
                  type: string
                propertyNames:
                  type: string
                type: object
              provider:
                enum:
                  - google
                  - apple
                  - github
                  - microsoft
                  - generic_oidc
                type: string
              provider_client_id:
                minLength: 1
                type: string
              provider_key:
                maxLength: 100
                minLength: 1
                pattern: ^[a-z0-9]+(?:[_-][a-z0-9]+)*$
                type: string
              scopes:
                items:
                  maxLength: 100
                  minLength: 1
                  pattern: ^\S+$
                  type: string
                maxItems: 20
                type: array
              status:
                enum:
                  - active
                  - disabled
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - id
              - environment_id
              - provider
              - mode
              - provider_key
              - issuer
              - provider_client_id
              - scopes
              - profile_mapping
              - status
              - owner_confirmed
              - created_at
              - updated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    ConnectionUpdateRequest:
      additionalProperties: false
      properties:
        issuer:
          format: uri
          type: string
        owner_confirmed:
          type: boolean
        profile_mapping:
          additionalProperties:
            type: string
          propertyNames:
            type: string
          type: object
        provider_client_id:
          minLength: 1
          type: string
        provider_client_secret:
          minLength: 1
          type: string
        scopes:
          items:
            maxLength: 100
            minLength: 1
            pattern: ^\S+$
            type: string
          maxItems: 20
          type: array
        status:
          enum:
            - active
            - disabled
          type: string
      type: object
    Domain:
      additionalProperties: false
      properties:
        activated_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        hostname:
          maxLength: 253
          minLength: 1
          type: string
        id:
          pattern: ^dom_[a-z2-7]{32}$
          type: string
        rp_enabled:
          type: boolean
        status:
          enum:
            - pending
            - active
            - moved
            - failed
            - deleting
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        validation_errors:
          items:
            minLength: 1
            type: string
          type: array
      required:
        - id
        - environment_id
        - hostname
        - status
        - rp_enabled
        - validation_errors
        - created_at
        - updated_at
        - activated_at
      type: object
    DomainCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        hostname:
          maxLength: 253
          minLength: 1
          type: string
        rp_enabled:
          default: false
          type: boolean
      required:
        - environment_id
        - hostname
      type: object
    DomainDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        id:
          pattern: ^dom_[a-z2-7]{32}$
          type: string
      required:
        - id
        - deleted
      type: object
    DomainListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              activated_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              hostname:
                maxLength: 253
                minLength: 1
                type: string
              id:
                pattern: ^dom_[a-z2-7]{32}$
                type: string
              rp_enabled:
                type: boolean
              status:
                enum:
                  - pending
                  - active
                  - moved
                  - failed
                  - deleting
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              validation_errors:
                items:
                  minLength: 1
                  type: string
                type: array
            required:
              - id
              - environment_id
              - hostname
              - status
              - rp_enabled
              - validation_errors
              - created_at
              - updated_at
              - activated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    DomainUpdateRequest:
      additionalProperties: false
      properties:
        rp_enabled:
          type: boolean
      required:
        - rp_enabled
      type: object
    Environment:
      additionalProperties: false
      properties:
        config_version:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        interaction_domain:
          minLength: 1
          type: string
        issuer:
          format: uri
          type: string
        name:
          maxLength: 200
          minLength: 1
          type: string
        project_id:
          pattern: ^prj_[a-z2-7]{32}$
          type: string
        rp_id:
          minLength: 1
          type: string
        status:
          enum:
            - active
            - suspended
            - deleted
          type: string
        type:
          enum:
            - test
            - production
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - project_id
        - type
        - name
        - status
        - issuer
        - interaction_domain
        - rp_id
        - config_version
        - created_at
        - updated_at
      type: object
    EnvironmentCreateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        project_id:
          pattern: ^prj_[a-z2-7]{32}$
          type: string
        type:
          enum:
            - test
            - production
          type: string
      required:
        - project_id
        - type
        - name
      type: object
    EnvironmentDeleteResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        status:
          const: deleted
          type: string
      required:
        - id
        - status
      type: object
    EnvironmentListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              config_version:
                maximum: 9007199254740991
                minimum: 0
                type: integer
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              interaction_domain:
                minLength: 1
                type: string
              issuer:
                format: uri
                type: string
              name:
                maxLength: 200
                minLength: 1
                type: string
              project_id:
                pattern: ^prj_[a-z2-7]{32}$
                type: string
              rp_id:
                minLength: 1
                type: string
              status:
                enum:
                  - active
                  - suspended
                  - deleted
                type: string
              type:
                enum:
                  - test
                  - production
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - id
              - project_id
              - type
              - name
              - status
              - issuer
              - interaction_domain
              - rp_id
              - config_version
              - created_at
              - updated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    EnvironmentSettingsRequest:
      additionalProperties: false
      properties:
        impersonation_enabled:
          type: boolean
      required:
        - impersonation_enabled
      type: object
    EnvironmentSettingsResponse:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        impersonation_enabled:
          type: boolean
      required:
        - environment_id
        - impersonation_enabled
      type: object
    EnvironmentThemeRequest:
      additionalProperties: {}
      propertyNames:
        type: string
      type: object
    EnvironmentThemeResponse:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        theme:
          additionalProperties: {}
          propertyNames:
            type: string
          type: object
        version:
          type: number
      required:
        - environment_id
        - version
        - theme
      type: object
    EnvironmentUpdateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        status:
          enum:
            - active
            - suspended
          type: string
      type: object
    ImpersonationCreateRequest:
      additionalProperties: false
      properties:
        duration_minutes:
          maximum: 15
          minimum: 1
          type: integer
        reason:
          maxLength: 1000
          minLength: 10
          type: string
        user_id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
      required:
        - user_id
        - reason
        - duration_minutes
      type: object
    ImpersonationCreateResponse:
      additionalProperties: false
      properties:
        actor_user_id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        expires_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        forbidden_scopes:
          items:
            enum:
              - workspaces:read
              - workspaces:write
              - workspace_members:read
              - projects:read
              - projects:write
              - environments:read
              - environments:write
              - clients:read
              - clients:write
              - clients:rotate_secret
              - connections:read
              - connections:write
              - domains:read
              - domains:write
              - users:read
              - users:write
              - users:block
              - users:delete
              - user_identities:read
              - user_identities:write
              - user_passkeys:read
              - user_passkeys:write
              - user_sessions:read
              - user_sessions:write
              - user_data_jobs:read
              - user_data_jobs:write
              - webhooks:read
              - webhooks:write
              - webhooks:rotate_secret
              - webhooks:test
              - audit_events:read
              - usage:read
              - introspect
              - billing:read
              - billing:write
              - api_keys:read
              - api_keys:write
              - impersonation:create
            type: string
          type: array
        impersonated_user_id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        reason:
          maxLength: 1000
          minLength: 10
          type: string
        started_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - actor_user_id
        - impersonated_user_id
        - reason
        - started_at
        - expires_at
        - forbidden_scopes
      type: object
    ImpersonationStopResponse:
      additionalProperties: false
      properties:
        stopped:
          const: true
          type: boolean
      required:
        - stopped
      type: object
    ManagementApiKeyCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        expires_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        name:
          maxLength: 200
          minLength: 1
          type: string
        scopes:
          items:
            enum:
              - workspaces:read
              - workspaces:write
              - workspace_members:read
              - projects:read
              - projects:write
              - environments:read
              - environments:write
              - clients:read
              - clients:write
              - clients:rotate_secret
              - connections:read
              - connections:write
              - domains:read
              - domains:write
              - users:read
              - users:write
              - users:block
              - users:delete
              - user_identities:read
              - user_identities:write
              - user_passkeys:read
              - user_passkeys:write
              - user_sessions:read
              - user_sessions:write
              - user_data_jobs:read
              - user_data_jobs:write
              - webhooks:read
              - webhooks:write
              - webhooks:rotate_secret
              - webhooks:test
              - audit_events:read
              - usage:read
              - introspect
              - billing:read
              - billing:write
              - api_keys:read
              - api_keys:write
              - impersonation:create
            type: string
          maxItems: 38
          minItems: 1
          type: array
        workspace_id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
      required:
        - workspace_id
        - name
        - scopes
      type: object
    ManagementApiKeyCreateResponse:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        created_by:
          minLength: 1
          type: string
        environment_id:
          anyOf:
            - pattern: ^env_[a-z2-7]{32}$
              type: string
            - type: "null"
        expires_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        id:
          pattern: ^mky_[a-z2-7]{32}$
          type: string
        last_used_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        name:
          maxLength: 200
          minLength: 1
          type: string
        prefix:
          minLength: 1
          type: string
        revoked_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        scopes:
          items:
            enum:
              - workspaces:read
              - workspaces:write
              - workspace_members:read
              - projects:read
              - projects:write
              - environments:read
              - environments:write
              - clients:read
              - clients:write
              - clients:rotate_secret
              - connections:read
              - connections:write
              - domains:read
              - domains:write
              - users:read
              - users:write
              - users:block
              - users:delete
              - user_identities:read
              - user_identities:write
              - user_passkeys:read
              - user_passkeys:write
              - user_sessions:read
              - user_sessions:write
              - user_data_jobs:read
              - user_data_jobs:write
              - webhooks:read
              - webhooks:write
              - webhooks:rotate_secret
              - webhooks:test
              - audit_events:read
              - usage:read
              - introspect
              - billing:read
              - billing:write
              - api_keys:read
              - api_keys:write
              - impersonation:create
            type: string
          minItems: 1
          type: array
        secret:
          pattern: ^sk_(?:live|test)_[A-Za-z0-9_-]{20,}$
          type: string
        workspace_id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
      required:
        - id
        - workspace_id
        - environment_id
        - name
        - prefix
        - scopes
        - last_used_at
        - expires_at
        - revoked_at
        - created_by
        - created_at
        - secret
      type: object
    ManagementApiKeyListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              created_by:
                minLength: 1
                type: string
              environment_id:
                anyOf:
                  - pattern: ^env_[a-z2-7]{32}$
                    type: string
                  - type: "null"
              expires_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              id:
                pattern: ^mky_[a-z2-7]{32}$
                type: string
              last_used_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              name:
                maxLength: 200
                minLength: 1
                type: string
              prefix:
                minLength: 1
                type: string
              revoked_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              scopes:
                items:
                  enum:
                    - workspaces:read
                    - workspaces:write
                    - workspace_members:read
                    - projects:read
                    - projects:write
                    - environments:read
                    - environments:write
                    - clients:read
                    - clients:write
                    - clients:rotate_secret
                    - connections:read
                    - connections:write
                    - domains:read
                    - domains:write
                    - users:read
                    - users:write
                    - users:block
                    - users:delete
                    - user_identities:read
                    - user_identities:write
                    - user_passkeys:read
                    - user_passkeys:write
                    - user_sessions:read
                    - user_sessions:write
                    - user_data_jobs:read
                    - user_data_jobs:write
                    - webhooks:read
                    - webhooks:write
                    - webhooks:rotate_secret
                    - webhooks:test
                    - audit_events:read
                    - usage:read
                    - introspect
                    - billing:read
                    - billing:write
                    - api_keys:read
                    - api_keys:write
                    - impersonation:create
                  type: string
                minItems: 1
                type: array
              workspace_id:
                pattern: ^wsp_[a-z2-7]{32}$
                type: string
            required:
              - id
              - workspace_id
              - environment_id
              - name
              - prefix
              - scopes
              - last_used_at
              - expires_at
              - revoked_at
              - created_by
              - created_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    ManagementApiKeyRevokeResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^mky_[a-z2-7]{32}$
          type: string
        revoked:
          const: true
          type: boolean
      required:
        - id
        - revoked
      type: object
    MauUsageResponse:
      additionalProperties: false
      properties:
        billing_activated:
          type: boolean
        billing_month:
          pattern: ^\d{4}-(?:0[1-9]|1[0-2])$
          type: string
        environments:
          items:
            additionalProperties: false
            properties:
              count:
                maximum: 9007199254740991
                minimum: 0
                type: integer
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
            required:
              - environment_id
              - count
            type: object
          type: array
        free_tier_limit:
          const: 30000
          type: number
        grace_period:
          additionalProperties: false
          properties:
            expires_at:
              anyOf:
                - format: date-time
                  pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                  type: string
                - type: "null"
            new_user_creation_blocked:
              type: boolean
            started_at:
              anyOf:
                - format: date-time
                  pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                  type: string
                - type: "null"
            status:
              enum:
                - none
                - active
                - expired
              type: string
          required:
            - status
            - started_at
            - expires_at
            - new_user_creation_blocked
          type: object
        percent_used:
          minimum: 0
          type: number
        threshold_reached:
          anyOf:
            - anyOf:
                - const: 80
                  type: number
                - const: 95
                  type: number
                - const: 100
                  type: number
            - type: "null"
        total_count:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        workspace_id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
      required:
        - workspace_id
        - billing_month
        - total_count
        - free_tier_limit
        - percent_used
        - threshold_reached
        - billing_activated
        - grace_period
        - environments
      type: object
    ProblemDetails:
      additionalProperties: false
      properties:
        code:
          type: string
        detail:
          type: string
        request_id:
          pattern: ^req_[a-z2-7]{32}$
          type: string
        status:
          maximum: 599
          minimum: 100
          type: integer
        title:
          minLength: 1
          type: string
        type:
          minLength: 1
          type: string
      required:
        - type
        - title
        - status
      type: object
    Project:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        deleted_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        id:
          pattern: ^prj_[a-z2-7]{32}$
          type: string
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        workspace_id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
      required:
        - id
        - workspace_id
        - name
        - slug
        - created_at
        - updated_at
        - deleted_at
      type: object
    ProjectCreateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
        workspace_id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
      required:
        - workspace_id
        - name
      type: object
    ProjectDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        id:
          pattern: ^prj_[a-z2-7]{32}$
          type: string
      required:
        - id
        - deleted
      type: object
    ProjectListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              deleted_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              id:
                pattern: ^prj_[a-z2-7]{32}$
                type: string
              name:
                maxLength: 200
                minLength: 1
                type: string
              slug:
                maxLength: 63
                minLength: 1
                pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              workspace_id:
                pattern: ^wsp_[a-z2-7]{32}$
                type: string
            required:
              - id
              - workspace_id
              - name
              - slug
              - created_at
              - updated_at
              - deleted_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    ProjectUpdateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
      type: object
    RpMigration:
      additionalProperties: false
      properties:
        active_rp_id:
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        legacy_disabled_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        legacy_only_users:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        legacy_rp_id:
          anyOf:
            - type: string
            - type: "null"
        migrated_share:
          maximum: 1
          minimum: 0
          type: number
        migrated_users:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        total_users:
          maximum: 9007199254740991
          minimum: 0
          type: integer
      required:
        - environment_id
        - active_rp_id
        - legacy_rp_id
        - legacy_disabled_at
        - total_users
        - migrated_users
        - legacy_only_users
        - migrated_share
      type: object
    RpMigrationDisableLegacyRequest:
      additionalProperties: false
      properties:
        confirm_rp_id:
          minLength: 1
          type: string
      required:
        - confirm_rp_id
      type: object
    ThemePreviewCssResponse:
      additionalProperties: false
      properties:
        variables:
          additionalProperties:
            type: string
          propertyNames:
            type: string
          type: object
      required:
        - variables
      type: object
    User:
      additionalProperties: false
      properties:
        avatar_url:
          anyOf:
            - format: uri
              type: string
            - type: "null"
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        email:
          anyOf:
            - format: email
              pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
              type: string
            - type: "null"
        email_verified:
          type: boolean
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        last_login_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        locale:
          anyOf:
            - type: string
            - type: "null"
        metadata:
          additionalProperties: {}
          propertyNames:
            type: string
          type: object
        name:
          anyOf:
            - type: string
            - type: "null"
        status:
          enum:
            - active
            - blocked
            - pending_deletion
          type: string
        timezone:
          anyOf:
            - type: string
            - type: "null"
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - email
        - email_verified
        - name
        - avatar_url
        - locale
        - timezone
        - status
        - metadata
        - created_at
        - updated_at
        - last_login_at
      type: object
    UserBlockRequest:
      additionalProperties: false
      properties:
        reason:
          maxLength: 1000
          minLength: 1
          type: string
      type: object
    UserBlockResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        status:
          const: blocked
          type: string
      required:
        - id
        - status
      type: object
    UserCreateRequest:
      additionalProperties: false
      properties:
        avatar_url:
          format: uri
          type: string
        email:
          format: email
          pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
          type: string
        email_verified:
          default: false
          type: boolean
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        locale:
          maxLength: 35
          minLength: 1
          type: string
        metadata:
          additionalProperties: {}
          default: {}
          propertyNames:
            type: string
          type: object
        name:
          maxLength: 200
          minLength: 1
          type: string
        timezone:
          maxLength: 64
          minLength: 1
          type: string
      required:
        - environment_id
        - email
      type: object
    UserDeleteResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        status:
          const: pending_deletion
          type: string
      required:
        - id
        - status
      type: object
    UserExportJob:
      additionalProperties: false
      properties:
        completed_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        contents:
          items:
            enum:
              - profile
              - emails
              - linked_identities
              - passkey_metadata
              - sessions
              - consent
              - audit_events
            type: string
          type: array
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        created_by:
          additionalProperties: false
          properties:
            actor_id:
              minLength: 1
              type: string
            actor_type:
              enum:
                - workspace_member
                - api_key
              type: string
          required:
            - actor_type
            - actor_id
          type: object
        download_url:
          anyOf:
            - format: uri
              type: string
            - type: "null"
        download_url_expires_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        id:
          pattern: ^job_[a-z2-7]{32}$
          type: string
        status:
          enum:
            - pending
            - processing
            - completed
            - failed
          type: string
        target_user_id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - target_user_id
        - status
        - contents
        - download_url
        - download_url_expires_at
        - created_by
        - created_at
        - updated_at
        - completed_at
      type: object
    UserExportJobCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        target_user_id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
      required:
        - environment_id
        - target_user_id
      type: object
    UserExportJobDownloadResponse:
      additionalProperties: {}
      propertyNames:
        type: string
      type: object
    UserIdentityDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        identity_id:
          pattern: ^idn_[a-z2-7]{32}$
          type: string
      required:
        - identity_id
        - deleted
      type: object
    UserIdentityListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              identity_id:
                pattern: ^idn_[a-z2-7]{32}$
                type: string
              last_used_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              linked_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              provider:
                enum:
                  - google
                  - apple
                  - github
                  - microsoft
                  - generic_oidc
                type: string
              user_id:
                pattern: ^usr_[a-z2-7]{32}$
                type: string
            required:
              - identity_id
              - user_id
              - provider
              - linked_at
              - last_used_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    UserImportJob:
      additionalProperties: false
      properties:
        completed_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        created_by:
          additionalProperties: false
          properties:
            actor_id:
              minLength: 1
              type: string
            actor_type:
              enum:
                - workspace_member
                - api_key
              type: string
          required:
            - actor_type
            - actor_id
          type: object
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        error_report_url:
          anyOf:
            - format: uri
              type: string
            - type: "null"
        failed_records:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        format:
          enum:
            - json
            - csv
          type: string
        id:
          pattern: ^job_[a-z2-7]{32}$
          type: string
        processed_records:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        source_url:
          format: uri
          type: string
        status:
          enum:
            - pending
            - processing
            - completed
            - failed
          type: string
        succeeded_records:
          maximum: 9007199254740991
          minimum: 0
          type: integer
        total_records:
          anyOf:
            - maximum: 9007199254740991
              minimum: 0
              type: integer
            - type: "null"
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - environment_id
        - status
        - format
        - source_url
        - total_records
        - processed_records
        - succeeded_records
        - failed_records
        - error_report_url
        - created_by
        - created_at
        - updated_at
        - completed_at
      type: object
    UserImportJobCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        format:
          enum:
            - json
            - csv
          type: string
        source_url:
          format: uri
          type: string
      required:
        - environment_id
        - format
        - source_url
      type: object
    UserImportJobErrorReport:
      items:
        additionalProperties: false
        properties:
          error:
            type: string
          index:
            type: number
        required:
          - index
          - error
        type: object
      type: array
    UserListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              avatar_url:
                anyOf:
                  - format: uri
                    type: string
                  - type: "null"
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              email:
                anyOf:
                  - format: email
                    pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
                    type: string
                  - type: "null"
              email_verified:
                type: boolean
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              id:
                pattern: ^usr_[a-z2-7]{32}$
                type: string
              last_login_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              locale:
                anyOf:
                  - type: string
                  - type: "null"
              metadata:
                additionalProperties: {}
                propertyNames:
                  type: string
                type: object
              name:
                anyOf:
                  - type: string
                  - type: "null"
              status:
                enum:
                  - active
                  - blocked
                  - pending_deletion
                type: string
              timezone:
                anyOf:
                  - type: string
                  - type: "null"
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - id
              - environment_id
              - email
              - email_verified
              - name
              - avatar_url
              - locale
              - timezone
              - status
              - metadata
              - created_at
              - updated_at
              - last_login_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    UserPasskeyDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        passkey_id:
          pattern: ^psk_[a-z2-7]{32}$
          type: string
      required:
        - passkey_id
        - deleted
      type: object
    UserPasskeyListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              backed_up:
                type: boolean
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              device_type:
                anyOf:
                  - enum:
                      - single_device
                      - multi_device
                    type: string
                  - type: "null"
              last_used_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              name:
                anyOf:
                  - type: string
                  - type: "null"
              passkey_id:
                pattern: ^psk_[a-z2-7]{32}$
                type: string
              transports:
                items:
                  enum:
                    - ble
                    - hybrid
                    - internal
                    - nfc
                    - usb
                  type: string
                type: array
              user_id:
                pattern: ^usr_[a-z2-7]{32}$
                type: string
            required:
              - passkey_id
              - user_id
              - name
              - created_at
              - last_used_at
              - device_type
              - backed_up
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    UserSessionListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              absolute_expires_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              client_id:
                pattern: ^cli_[a-z2-7]{32}$
                type: string
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              device_name:
                anyOf:
                  - type: string
                  - type: "null"
              idle_expires_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              last_active_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              revoked_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              session_id:
                pattern: ^ses_[a-z2-7]{32}$
                type: string
              user_id:
                pattern: ^usr_[a-z2-7]{32}$
                type: string
            required:
              - session_id
              - user_id
              - client_id
              - device_name
              - created_at
              - last_active_at
              - idle_expires_at
              - absolute_expires_at
              - revoked_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    UserSessionRevokeResponse:
      additionalProperties: false
      properties:
        revoked:
          const: true
          type: boolean
        session_id:
          pattern: ^ses_[a-z2-7]{32}$
          type: string
      required:
        - session_id
        - revoked
      type: object
    UserSessionsRevokeAllResponse:
      additionalProperties: false
      properties:
        revoked:
          const: true
          type: boolean
      required:
        - revoked
      type: object
    UserUnblockResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^usr_[a-z2-7]{32}$
          type: string
        status:
          const: active
          type: string
      required:
        - id
        - status
      type: object
    UserUpdateRequest:
      additionalProperties: false
      properties:
        avatar_url:
          format: uri
          type: string
        locale:
          maxLength: 35
          minLength: 1
          type: string
        metadata:
          additionalProperties: {}
          propertyNames:
            type: string
          type: object
        name:
          maxLength: 200
          minLength: 1
          type: string
        timezone:
          maxLength: 64
          minLength: 1
          type: string
      type: object
    Webhook:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        event_types:
          items:
            enum:
              - user.created
              - user.updated
              - user.deleted
              - user.blocked
              - identity.linked
              - identity.unlinked
              - passkey.created
              - passkey.deleted
              - session.created
              - session.revoked
              - login.succeeded
              - login.failed
              - email.delivery.bounced
              - mau.threshold_reached
            type: string
          minItems: 1
          type: array
        id:
          pattern: ^whk_[a-z2-7]{32}$
          type: string
        status:
          enum:
            - active
            - disabled
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        url:
          format: uri
          type: string
      required:
        - id
        - environment_id
        - url
        - event_types
        - status
        - created_at
        - updated_at
      type: object
    WebhookCreateRequest:
      additionalProperties: false
      properties:
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        event_types:
          items:
            enum:
              - user.created
              - user.updated
              - user.deleted
              - user.blocked
              - identity.linked
              - identity.unlinked
              - passkey.created
              - passkey.deleted
              - session.created
              - session.revoked
              - login.succeeded
              - login.failed
              - email.delivery.bounced
              - mau.threshold_reached
            type: string
          minItems: 1
          type: array
        url:
          format: uri
          type: string
      required:
        - environment_id
        - url
        - event_types
      type: object
    WebhookCreateResponse:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        environment_id:
          pattern: ^env_[a-z2-7]{32}$
          type: string
        event_types:
          items:
            enum:
              - user.created
              - user.updated
              - user.deleted
              - user.blocked
              - identity.linked
              - identity.unlinked
              - passkey.created
              - passkey.deleted
              - session.created
              - session.revoked
              - login.succeeded
              - login.failed
              - email.delivery.bounced
              - mau.threshold_reached
            type: string
          minItems: 1
          type: array
        id:
          pattern: ^whk_[a-z2-7]{32}$
          type: string
        secret:
          minLength: 1
          type: string
        status:
          enum:
            - active
            - disabled
          type: string
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        url:
          format: uri
          type: string
      required:
        - id
        - environment_id
        - url
        - event_types
        - status
        - created_at
        - updated_at
        - secret
      type: object
    WebhookDeleteResponse:
      additionalProperties: false
      properties:
        deleted:
          const: true
          type: boolean
        id:
          pattern: ^whk_[a-z2-7]{32}$
          type: string
      required:
        - id
        - deleted
      type: object
    WebhookDeliveryListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              attempt:
                exclusiveMinimum: 0
                maximum: 9007199254740991
                type: integer
              duration_ms:
                maximum: 9007199254740991
                minimum: 0
                type: integer
              event_id:
                pattern: ^evt_[a-z2-7]{32}$
                type: string
              event_type:
                minLength: 1
                type: string
              id:
                pattern: ^dlv_[a-z2-7]{32}$
                type: string
              occurred_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              response_status_code:
                anyOf:
                  - maximum: 599
                    minimum: 100
                    type: integer
                  - type: "null"
              status:
                enum:
                  - pending
                  - delivered
                  - failed
                  - exhausted
                type: string
              webhook_id:
                pattern: ^whk_[a-z2-7]{32}$
                type: string
            required:
              - id
              - webhook_id
              - event_id
              - event_type
              - attempt
              - status
              - response_status_code
              - duration_ms
              - occurred_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    WebhookListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              environment_id:
                pattern: ^env_[a-z2-7]{32}$
                type: string
              event_types:
                items:
                  enum:
                    - user.created
                    - user.updated
                    - user.deleted
                    - user.blocked
                    - identity.linked
                    - identity.unlinked
                    - passkey.created
                    - passkey.deleted
                    - session.created
                    - session.revoked
                    - login.succeeded
                    - login.failed
                    - email.delivery.bounced
                    - mau.threshold_reached
                  type: string
                minItems: 1
                type: array
              id:
                pattern: ^whk_[a-z2-7]{32}$
                type: string
              status:
                enum:
                  - active
                  - disabled
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              url:
                format: uri
                type: string
            required:
              - id
              - environment_id
              - url
              - event_types
              - status
              - created_at
              - updated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    WebhookRotateSecretResponse:
      additionalProperties: false
      properties:
        id:
          pattern: ^whk_[a-z2-7]{32}$
          type: string
        rotated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        secret:
          minLength: 1
          type: string
      required:
        - id
        - secret
        - rotated_at
      type: object
    WebhookTestRequest:
      additionalProperties: false
      properties:
        event_type:
          enum:
            - user.created
            - user.updated
            - user.deleted
            - user.blocked
            - identity.linked
            - identity.unlinked
            - passkey.created
            - passkey.deleted
            - session.created
            - session.revoked
            - login.succeeded
            - login.failed
            - email.delivery.bounced
            - mau.threshold_reached
          type: string
      type: object
    WebhookTestResponse:
      additionalProperties: false
      properties:
        delivered:
          type: boolean
        requested_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        response_status:
          anyOf:
            - maximum: 599
              minimum: 100
              type: integer
            - type: "null"
        response_time_ms:
          anyOf:
            - maximum: 9007199254740991
              minimum: 0
              type: integer
            - type: "null"
      required:
        - delivered
        - response_status
        - response_time_ms
        - requested_at
      type: object
    WebhookUpdateRequest:
      additionalProperties: false
      properties:
        event_types:
          items:
            enum:
              - user.created
              - user.updated
              - user.deleted
              - user.blocked
              - identity.linked
              - identity.unlinked
              - passkey.created
              - passkey.deleted
              - session.created
              - session.revoked
              - login.succeeded
              - login.failed
              - email.delivery.bounced
              - mau.threshold_reached
            type: string
          minItems: 1
          type: array
        status:
          enum:
            - active
            - disabled
          type: string
        url:
          format: uri
          type: string
      type: object
    Workspace:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
        deleted_at:
          anyOf:
            - format: date-time
              pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
              type: string
            - type: "null"
        id:
          pattern: ^wsp_[a-z2-7]{32}$
          type: string
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
        status:
          enum:
            - active
            - past_due
            - suspended
            - deleted
          type: string
        stripe_customer_id:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
        updated_at:
          format: date-time
          pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          type: string
      required:
        - id
        - name
        - slug
        - status
        - stripe_customer_id
        - created_at
        - updated_at
        - deleted_at
      type: object
    WorkspaceCreateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
      required:
        - name
      type: object
    WorkspaceListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              deleted_at:
                anyOf:
                  - format: date-time
                    pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                    type: string
                  - type: "null"
              id:
                pattern: ^wsp_[a-z2-7]{32}$
                type: string
              name:
                maxLength: 200
                minLength: 1
                type: string
              slug:
                maxLength: 63
                minLength: 1
                pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
                type: string
              status:
                enum:
                  - active
                  - past_due
                  - suspended
                  - deleted
                type: string
              stripe_customer_id:
                anyOf:
                  - minLength: 1
                    type: string
                  - type: "null"
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - id
              - name
              - slug
              - status
              - stripe_customer_id
              - created_at
              - updated_at
              - deleted_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    WorkspaceMemberListResponse:
      additionalProperties: false
      properties:
        items:
          items:
            additionalProperties: false
            properties:
              created_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
              platform_user_id:
                minLength: 1
                type: string
              role:
                enum:
                  - owner
                  - admin
                  - developer
                  - support
                  - billing
                  - viewer
                type: string
              updated_at:
                format: date-time
                pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
                type: string
            required:
              - platform_user_id
              - role
              - created_at
              - updated_at
            type: object
          type: array
        next_cursor:
          anyOf:
            - minLength: 1
              type: string
            - type: "null"
      required:
        - items
        - next_cursor
      type: object
    WorkspaceUpdateRequest:
      additionalProperties: false
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        slug:
          maxLength: 63
          minLength: 1
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
      type: object
  securitySchemes:
    ManagementApiKey:
      description: "Management API key (`Authorization: Bearer sk_live_...`、test モードは `sk_test_...`)。key は HMAC のみ保存され、scope は最小化される (design.md §26.1, §11.12)。Dashboard session も利用可能。"
      scheme: bearer
      type: http
info:
  description: |-
    Workspace / Project / Environment / Client / User 等を管理する Management API (design.md §26) の OpenAPI 3.1 定義。

    共通仕様 (design.md §26.3):
    - 認証は `Authorization: Bearer sk_live_...` の Management API key (HMAC のみ保存、scope 最小化) または Dashboard session (§26.1)。
    - 一覧 API はカーソルページネーション。最大 page size は 100。
    - write API (POST/PATCH/DELETE) は `Idempotency-Key` ヘッダに対応。
    - 更新・削除は ETag / `If-Match` ヘッダによる条件付きリクエストに対応。
    - 全レスポンスに `X-Request-Id` ヘッダを付与。
    - エラーは RFC 9457 Problem Details (`application/problem+json`) で返却。
  title: パスワードレス認証基盤 Management API
  version: 0.1.0
jsonSchemaDialect: https://json-schema.org/draft/2020-12/schema
openapi: 3.1.0
paths:
  /api-keys:
    get:
      description: Workspace に発行された Management API key の一覧を返す。secret は作成時にのみ表示される (design.md §11.12, §26.1)。
      operationId: listManagementApiKeys
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Workspace ID (wsp_...)
          in: query
          name: workspace_id
          required: true
          schema:
            pattern: ^wsp_[a-z2-7]{32}$
            type: string
        - description: 対象 Environment ID (env_...) で絞り込み
          in: query
          name: environment_id
          required: false
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ManagementApiKeyListResponse"
          description: Management API key のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Management API key 一覧の取得
      tags:
        - API Keys
    post:
      description: Management API key を作成する。平文 secret はこのレスポンスで1回だけ表示される (design.md §11.12, §26.1)。
      operationId: createManagementApiKey
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ManagementApiKeyCreateRequest"
        description: 発行する key の名前・scope・Environment・有効期限
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ManagementApiKeyCreateResponse"
          description: 作成された Management API key (secret は1回だけ表示)
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Management API key の作成
      tags:
        - API Keys
  /api-keys/{apiKeyId}/revoke:
    post:
      description: Management API key を失効させる。リクエストボディはない。
      operationId: revokeManagementApiKey
      parameters:
        - description: Management API key ID (mky_...)
          in: path
          name: apiKeyId
          required: true
          schema:
            pattern: ^mky_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ManagementApiKeyRevokeResponse"
          description: 失効結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Management API key の失効
      tags:
        - API Keys
  /audit-events:
    get:
      description: 監査イベントのカーソルページネーション一覧を返す (design.md §12.11)。監査ログは追記専用で、通常 API から更新・削除はできない。`auth_partition_id` 等の内部ルーティング識別子は返さない。
      operationId: listAuditEvents
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - description: actor 種別で絞り込み
          in: query
          name: actor_type
          required: false
          schema:
            enum:
              - end_user
              - workspace_member
              - api_key
              - system
            type: string
        - description: アクション名で絞り込み
          in: query
          name: action
          required: false
          schema:
            minLength: 1
            type: string
        - description: 対象リソース種別で絞り込み
          in: query
          name: subject_type
          required: false
          schema:
            minLength: 1
            type: string
        - description: 対象リソース ID で絞り込み
          in: query
          name: subject_id
          required: false
          schema:
            minLength: 1
            type: string
        - description: success / failure で絞り込み
          in: query
          name: result
          required: false
          schema:
            enum:
              - success
              - failure
            type: string
        - description: この時刻以降に絞り込み (ISO 8601)
          in: query
          name: created_after
          required: false
          schema:
            format: date-time
            pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            type: string
        - description: この時刻以前に絞り込み (ISO 8601)
          in: query
          name: created_before
          required: false
          schema:
            format: date-time
            pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AuditEventListResponse"
          description: 監査イベントのページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: 監査イベント一覧の取得
      tags:
        - Audit Events
  /billing/checkout-session:
    post:
      description: 課金有効化のための Stripe Checkout セッションを作成する (design.md §28.5)。30,000 MAU を超えて継続利用するには Stripe Customer / Subscription / Payment Method の有効化が必要。
      operationId: createBillingCheckoutSession
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillingCheckoutSessionCreateRequest"
        description: 成功・キャンセル時のリダイレクト先
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillingCheckoutSessionCreateResponse"
          description: Checkout セッションのリダイレクト URL
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Stripe Checkout セッションの作成
      tags:
        - Billing
  /billing/portal-session:
    post:
      description: 既存の課金設定を管理するための Stripe Billing Portal セッションを作成する (design.md §28.5)。
      operationId: createBillingPortalSession
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BillingPortalSessionCreateRequest"
        description: 完了後のリダイレクト先
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BillingPortalSessionCreateResponse"
          description: Billing Portal のリダイレクト URL
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Stripe Billing Portal セッションの作成
      tags:
        - Billing
  /clients:
    get:
      description: "`environment_id` でスコープした Client の一覧を返す (design.md §11.5, §26.2)。`secret_hash` は返さない。"
      operationId: listClients
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - description: web_bff / web_spa / react_native で絞り込み
          in: query
          name: client_type
          required: false
          schema:
            enum:
              - web_bff
              - web_spa
              - react_native
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientListResponse"
          description: Client のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client 一覧の取得
      tags:
        - Clients
    post:
      description: Client を作成する (design.md §11.5, §7.4)。confidential client (`token_endpoint_auth_method` が `none` 以外) には `client_secret` をこのレスポンスで1回だけ表示する (§11.12 の display-once 規則)。public client には secret を発行しない (§15.4)。
      operationId: createClient
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ClientCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientCreateResponse"
          description: 作成された Client (confidential のみ client_secret を1回だけ表示)
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client の作成
      tags:
        - Clients
  /clients/{clientId}:
    delete:
      description: Client を削除する。If-Match による条件付き削除に対応 (design.md §26.3)。
      operationId: deleteClient
      parameters:
        - description: Client ID (cli_...)
          in: path
          name: clientId
          required: true
          schema:
            pattern: ^cli_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client の削除
      tags:
        - Clients
    get:
      description: 単一 Client を返す (design.md §11.5)。ETag ヘッダを付与する。
      operationId: getClient
      parameters:
        - description: Client ID (cli_...)
          in: path
          name: clientId
          required: true
          schema:
            pattern: ^cli_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Client"
          description: Client
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client の取得
      tags:
        - Clients
    patch:
      description: Client の設定を更新する (redirect_uris / allowed_origins / allowed_scopes / mobile_app 等、design.md §11.5-§11.8)。If-Match による条件付き更新に対応 (§26.3)。
      operationId: updateClient
      parameters:
        - description: Client ID (cli_...)
          in: path
          name: clientId
          required: true
          schema:
            pattern: ^cli_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ClientUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Client"
          description: 更新後の Client
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client の更新
      tags:
        - Clients
  /clients/{clientId}/rotate-secret:
    post:
      description: confidential client の secret をローテーションし、新しい平文 secret をこのレスポンスで1回だけ表示する (design.md §11.12 の display-once 規則)。リクエストボディはない。
      operationId: rotateClientSecret
      parameters:
        - description: Client ID (cli_...)
          in: path
          name: clientId
          required: true
          schema:
            pattern: ^cli_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ClientRotateSecretResponse"
          description: 新しい client_secret (1回だけ表示)
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Client secret のローテーション
      tags:
        - Clients
  /connections:
    get:
      description: "`environment_id` でスコープしたソーシャルプロバイダ Connection の一覧を返す (design.md §11.10, §26.2)。`secret_ciphertext` / `secret_iv` は返さない。"
      operationId: listConnections
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - description: プロバイダで絞り込み
          in: query
          name: provider
          required: false
          schema:
            enum:
              - google
              - apple
              - github
              - microsoft
              - generic_oidc
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConnectionListResponse"
          description: Connection のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Connection 一覧の取得
      tags:
        - Connections
    post:
      description: ソーシャルプロバイダ Connection を作成する (design.md §11.10, §20)。`provider_client_secret` は write-only で、サーバが暗号化して保存し (§20.4)、いかなるレスポンスにも現れない。
      operationId: createConnection
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectionCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Connection"
          description: 作成された Connection
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Connection の作成
      tags:
        - Connections
  /connections/{connectionId}:
    delete:
      description: Connection を削除する。If-Match による条件付き削除に対応 (design.md §26.3)。
      operationId: deleteConnection
      parameters:
        - description: Connection ID (con_...)
          in: path
          name: connectionId
          required: true
          schema:
            pattern: ^con_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConnectionDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Connection の削除
      tags:
        - Connections
    patch:
      description: Connection の設定を更新する。`provider_client_secret` を省略した場合は保存済みの secret を維持する。If-Match による条件付き更新に対応 (design.md §26.3)。
      operationId: updateConnection
      parameters:
        - description: Connection ID (con_...)
          in: path
          name: connectionId
          required: true
          schema:
            pattern: ^con_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectionUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Connection"
          description: 更新後の Connection
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Connection の更新
      tags:
        - Connections
  /domains:
    get:
      description: "`environment_id` でスコープした Custom Domain の一覧を返す (design.md §11.9, §26.2)。"
      operationId: listDomains
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - description: 検証ステータスで絞り込み
          in: query
          name: status
          required: false
          schema:
            enum:
              - pending
              - active
              - moved
              - failed
              - deleting
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DomainListResponse"
          description: Custom Domain のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain 一覧の取得
      tags:
        - Domains
    post:
      description: Custom Domain を作成する (design.md §11.9, §8.2)。作成直後は `pending` で、検証進行は `status` / `validation_errors` が報告する。
      operationId: createDomain
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DomainCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Domain"
          description: 作成された Custom Domain
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain の作成
      tags:
        - Domains
  /domains/{domainId}:
    delete:
      description: Custom Domain を削除する。旧 RP ID を無効化済みの Environment の `rp_enabled` Domain は削除できない (409 `legacy_rp_disabled`)。If-Match による条件付き削除に対応 (design.md §26.3)。
      operationId: deleteDomain
      parameters:
        - description: Custom Domain ID (dom_...)
          in: path
          name: domainId
          required: true
          schema:
            pattern: ^dom_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DomainDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain の削除
      tags:
        - Domains
    get:
      description: 単一 Custom Domain を返す (design.md §11.9)。ETag ヘッダを付与する。
      operationId: getDomain
      parameters:
        - description: Custom Domain ID (dom_...)
          in: path
          name: domainId
          required: true
          schema:
            pattern: ^dom_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Domain"
          description: Custom Domain
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain の取得
      tags:
        - Domains
    patch:
      description: "`rp_enabled` を切り替える (design.md §8.3)。有効化すると WebAuthn RP ID と hosted login の Interaction Domain の両方がこの Custom Domain に切り替わる (`active` の間のみ)。Environment ごとに有効化できるのは 1 件だけで、既に別の Domain が有効な場合は 409 `rp_domain_conflict`。旧 RP ID を無効化済みの Environment では `rp_enabled` を false にできない (409 `legacy_rp_disabled`)。If-Match による条件付き更新に対応 (design.md §26.3)。"
      operationId: updateDomain
      parameters:
        - description: Custom Domain ID (dom_...)
          in: path
          name: domainId
          required: true
          schema:
            pattern: ^dom_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DomainUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Domain"
          description: 更新後の Custom Domain
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain の更新
      tags:
        - Domains
  /domains/{domainId}/retry-validation:
    post:
      description: 検証をリトライする。`status` を `pending` へ戻し、過去の `validation_errors` をクリアする (design.md §11.9)。リクエストボディはない。
      operationId: retryDomainValidation
      parameters:
        - description: Custom Domain ID (dom_...)
          in: path
          name: domainId
          required: true
          schema:
            pattern: ^dom_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Domain"
          description: リトライ後の Custom Domain
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Custom Domain 検証のリトライ
      tags:
        - Domains
  /environments:
    get:
      description: "`project_id` でスコープした Environment の一覧を返す (design.md §11.4, §26.2)。"
      operationId: listEnvironments
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Project ID (prj_...)
          in: query
          name: project_id
          required: true
          schema:
            pattern: ^prj_[a-z2-7]{32}$
            type: string
        - description: test / production で絞り込み
          in: query
          name: type
          required: false
          schema:
            enum:
              - test
              - production
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentListResponse"
          description: Environment のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment 一覧の取得
      tags:
        - Environments
    post:
      description: Environment を作成する (design.md §11.4)。`issuer` / `interaction_domain` / `rp_id` はサーバが Environment ID とプラットフォームのルートドメインから導出し、以後固定される (§8)。
      operationId: createEnvironment
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EnvironmentCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Environment"
          description: 作成された Environment
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment の作成
      tags:
        - Environments
  /environments/{environmentId}:
    delete:
      description: Environment を削除 (`deleted`) する。If-Match による条件付き削除に対応 (design.md §26.3)。削除前に Environment の全カスタムドメインを退役させる (Cloudflare for SaaS の custom hostname と `<hostname>/*` Worker route を削除し、ドメインを `deleting` にする)。legacy RP 無効化後でも実行できる。退役に失敗した場合は Environment を削除せずエラーを返し、再実行で残りのドメインから再開する。
      operationId: deleteEnvironment
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment の削除
      tags:
        - Environments
    get:
      description: 単一 Environment を返す (design.md §11.4)。ETag ヘッダを付与する。
      operationId: getEnvironment
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Environment"
          description: Environment
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment の取得
      tags:
        - Environments
    patch:
      description: name / status (`active`/`suspended` のトグルのみ) を更新する。`deleted` への遷移は DELETE を使う。If-Match による条件付き更新に対応 (design.md §26.3)。
      operationId: updateEnvironment
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EnvironmentUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Environment"
          description: 更新後の Environment
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment の更新
      tags:
        - Environments
  /environments/{environmentId}/rp-migration:
    get:
      description: RP ID 移行 (design.md §8.3) の状況を返す。`rp_enabled` の active な custom domain があれば移行中で、`active_rp_id` はその hostname、`legacy_rp_id` は元の `rp_id`。ユーザー数は全 Auth partition を横断し、失効していない passkey のみを数える。
      operationId: getRpMigration
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RpMigration"
          description: RP ID 移行状況
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: RP ID 移行状況の取得
      tags:
        - Environments
  /environments/{environmentId}/rp-migration/disable-legacy:
    post:
      description: 移行中の Environment で旧 RP ID の passkey を不可逆に無効化する (design.md §8.3)。`confirm_rp_id` は旧 `rp_id` と一致する必要がある (不一致は 400 `confirmation_mismatch`)。移行中でなければ 409 `rp_migration_not_in_effect`。既に無効化済みなら冪等に 200 を返す。
      operationId: disableLegacyRp
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RpMigrationDisableLegacyRequest"
        description: 確認用の旧 RP ID
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RpMigration"
          description: 更新後の RP ID 移行状況
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: 旧 RP ID の無効化
      tags:
        - Environments
  /environments/{environmentId}/settings:
    get:
      description: Environment の管理設定を取得する。現在は impersonation の有効化状態を返す。
      operationId: getEnvironmentSettings
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentSettingsResponse"
          description: Environment settings
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment settings の取得
      tags:
        - Environment Settings
    patch:
      description: Environment の management settings を更新する。現在は impersonation の有効化状態を更新し、If-Match と Idempotency-Key には対応しない。
      operationId: updateEnvironmentSettings
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EnvironmentSettingsRequest"
        description: Environment settings
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentSettingsResponse"
          description: 更新後の Environment settings
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment settings の更新
      tags:
        - Environment Settings
  /environments/{environmentId}/theme:
    get:
      description: Hosted Login の Environment theme とバージョンを取得する。レスポンスには現在値の ETag が付与される。
      operationId: getEnvironmentTheme
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentThemeResponse"
          description: Environment theme
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment theme の取得
      tags:
        - Themes
    put:
      description: Hosted Login の theme を更新する。theme-schema で検証し、If-Match による条件付き更新に対応する。Idempotency-Key には対応しない。
      operationId: putEnvironmentTheme
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EnvironmentThemeRequest"
        description: theme-schema に従う theme document
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EnvironmentThemeResponse"
          description: 更新後の Environment theme
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment theme の更新
      tags:
        - Themes
  /environments/{environmentId}/theme/preview-css:
    get:
      description: 保存済み theme を Hosted Login preview 用の CSS custom property map へ変換して返す。
      operationId: getEnvironmentThemePreviewCss
      parameters:
        - description: Environment ID (env_...)
          in: path
          name: environmentId
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ThemePreviewCssResponse"
          description: Theme CSS variables
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Environment theme の preview CSS 取得
      tags:
        - Themes
  /impersonation:
    post:
      description: Owner/Admin が理由と期限を指定して Environment 内の User を impersonate する。`environment_id` は query parameter で指定する。冪等キーには対応しない。
      operationId: startImpersonation
      parameters:
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ImpersonationCreateRequest"
        description: 対象 User・理由・有効期間
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImpersonationCreateResponse"
          description: 開始された impersonation session
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Impersonation session の開始
      tags:
        - Impersonation
  /impersonation/stop:
    post:
      description: 現在の impersonation session を終了する。リクエストボディ・冪等キー・前提条件ヘッダはいずれも受け付けない。
      operationId: stopImpersonation
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImpersonationStopResponse"
          description: 終了結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Impersonation session の終了
      tags:
        - Impersonation
  /projects:
    get:
      description: "`workspace_id` でスコープした Project の一覧を返す (design.md §11.3, §26.2)。"
      operationId: listProjects
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Workspace ID (wsp_...)
          in: query
          name: workspace_id
          required: true
          schema:
            pattern: ^wsp_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProjectListResponse"
          description: Project のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Project 一覧の取得
      tags:
        - Projects
    post:
      description: Project を作成する (design.md §11.3)。`slug` 省略時は `name` から導出される。
      operationId: createProject
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProjectCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Project"
          description: 作成された Project
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Project の作成
      tags:
        - Projects
  /projects/{projectId}:
    delete:
      description: Project を論理削除する (design.md §11.3 `deleted_at`)。If-Match による条件付き削除に対応 (§26.3)。
      operationId: deleteProject
      parameters:
        - description: Project ID (prj_...)
          in: path
          name: projectId
          required: true
          schema:
            pattern: ^prj_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProjectDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Project の削除
      tags:
        - Projects
    get:
      description: 単一 Project を返す (design.md §11.3)。ETag ヘッダを付与する。
      operationId: getProject
      parameters:
        - description: Project ID (prj_...)
          in: path
          name: projectId
          required: true
          schema:
            pattern: ^prj_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Project"
          description: Project
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Project の取得
      tags:
        - Projects
    patch:
      description: name / slug を更新する。If-Match による条件付き更新に対応 (design.md §26.3)。
      operationId: updateProject
      parameters:
        - description: Project ID (prj_...)
          in: path
          name: projectId
          required: true
          schema:
            pattern: ^prj_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProjectUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Project"
          description: 更新後の Project
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Project の更新
      tags:
        - Projects
  /usage/mau:
    get:
      description: Workspace 単位の MAU 集計を返す (design.md §28)。無料枠 (30,000 MAU)、80%/95%/100% の threshold 到達状況、課金有効化状態、72 時間 grace period の状態を含む (§28.5)。
      operationId: getMauUsage
      parameters:
        - description: 課金月 (YYYY-MM)。省略時は現在の課金月
          in: query
          name: billing_month
          required: false
          schema:
            pattern: ^\d{4}-(?:0[1-9]|1[0-2])$
            type: string
        - description: environments 内訳を単一 Environment に絞り込み
          in: query
          name: environment_id
          required: false
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MauUsageResponse"
          description: MAU 使用量
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: MAU 使用量の取得
      tags:
        - Usage
  /user-export-jobs:
    post:
      description: 非同期のユーザーエクスポートジョブを作成する (design.md §26.2)。エクスポート内容は design.md §33.3 の固定リスト (private key・provider token・内部リスクスコアは含まない)。
      operationId: createUserExportJob
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserExportJobCreateRequest"
        description: 対象 Environment と User
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserExportJob"
          description: 作成されたエクスポートジョブ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーエクスポートジョブの作成
      tags:
        - User Data Jobs
  /user-export-jobs/{jobId}:
    get:
      description: エクスポートジョブの状態を返す。`completed` 後は期間限定の署名付き R2 ダウンロード URL を含む。
      operationId: getUserExportJob
      parameters:
        - description: ジョブID (job_...)
          in: path
          name: jobId
          required: true
          schema:
            pattern: ^job_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserExportJob"
          description: エクスポートジョブ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーエクスポートジョブの取得
      tags:
        - User Data Jobs
  /user-export-jobs/{jobId}/download:
    get:
      description: 完了したユーザーエクスポートジョブの JSON artifact を返す。ダウンロードの有効期限切れ後は Gone (410) を返す。
      operationId: downloadUserExportJob
      parameters:
        - description: ジョブID (job_...)
          in: path
          name: jobId
          required: true
          schema:
            pattern: ^job_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserExportJobDownloadResponse"
          description: ユーザーエクスポート JSON artifact
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "410":
          $ref: "#/components/responses/Gone"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーエクスポート結果のダウンロード
      tags:
        - User Data Jobs
  /user-import-jobs:
    post:
      description: 非同期のユーザーインポートジョブを作成する (design.md §26.2)。ソースレコードは R2/顧客ホストの HTTPS URL から取得し、ジョブリソースへは進捗と行単位エラーレポートの URL のみ保持する (§14.0 の 64 KB 上限)。
      operationId: createUserImportJob
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserImportJobCreateRequest"
        description: インポート形式とソース URL
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserImportJob"
          description: 作成されたインポートジョブ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーインポートジョブの作成
      tags:
        - User Data Jobs
  /user-import-jobs/{jobId}:
    get:
      description: インポートジョブの状態・進捗・エラーレポート URL を返す。
      operationId: getUserImportJob
      parameters:
        - description: ジョブID (job_...)
          in: path
          name: jobId
          required: true
          schema:
            pattern: ^job_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserImportJob"
          description: インポートジョブ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーインポートジョブの取得
      tags:
        - User Data Jobs
  /user-import-jobs/{jobId}/errors:
    get:
      description: インポートに失敗した行のエラーレポートを JSON array で返す。レポートがない場合は Not Found を返す。
      operationId: getUserImportJobErrors
      parameters:
        - description: ジョブID (job_...)
          in: path
          name: jobId
          required: true
          schema:
            pattern: ^job_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserImportJobErrorReport"
          description: 行単位のインポートエラーレポート
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: ユーザーインポートジョブのエラーレポート取得
      tags:
        - User Data Jobs
  /users:
    get:
      description: "`environment_id` でスコープした User の一覧を返す (design.md §12.1, §26.2)。`email` は `user_emails.email_ciphertext` をサーバ側で復号した表示値。`auth_partition_id` 等の内部ルーティング識別子は返さない。"
      operationId: listUsers
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - description: ユーザーステータスで絞り込み
          in: query
          name: status
          required: false
          schema:
            enum:
              - active
              - blocked
              - pending_deletion
            type: string
        - description: name/email のフリーテキスト検索
          in: query
          name: search
          required: false
          schema:
            maxLength: 200
            minLength: 1
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserListResponse"
          description: User のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User 一覧の取得
      tags:
        - Users
    post:
      description: 管理者による User 作成 (design.md §12.1)。信頼できるソースからの一括インポート等では `email_verified` を事前検証済みにできる。
      operationId: createUser
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
          description: 作成された User
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の作成
      tags:
        - Users
  /users/{userId}:
    delete:
      description: User を論理削除 (`pending_deletion`) へ移行する (design.md §33.1)。If-Match による条件付き削除に対応 (§26.3)。
      operationId: deleteUser
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の削除
      tags:
        - Users
    get:
      description: 単一 User を返す (design.md §12.1)。ETag ヘッダを付与する。
      operationId: getUser
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
          description: User
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の取得
      tags:
        - Users
    patch:
      description: プロフィール・metadata を更新する。`email` はこの route では変更できない (新旧両メールの検証が必要な design.md §25 のフローであり、管理者変更にはさらに Owner/Admin・理由・監査記録が必要)。If-Match による条件付き更新に対応 (§26.3)。
      operationId: updateUser
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
          description: 更新後の User
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の更新
      tags:
        - Users
  /users/{userId}/block:
    post:
      description: "User をブロックする。`UserSecurityDO` の block 状態と security version が更新され、既発行 token は introspection で `active: false` になる (design.md §15.8)。"
      operationId: blockUser
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserBlockRequest"
        description: ブロック理由 (任意)
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserBlockResponse"
          description: ブロック結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User のブロック
      tags:
        - Users
  /users/{userId}/identities:
    get:
      description: 指定 User のリンク済みソーシャルアイデンティティ一覧を返す (design.md §12.3)。`provider_subject` や token ciphertext は返さない。
      operationId: listUserIdentities
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserIdentityListResponse"
          description: アイデンティティのページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の外部アイデンティティ一覧の取得
      tags:
        - User Sub-resources
  /users/{userId}/identities/{identityId}:
    delete:
      description: 指定アイデンティティのリンクを解除する。credential 変更に相当するため `user_identities:write` scope が必要 (design.md §25, §27.2)。If-Match による条件付き削除に対応 (§26.3)。
      operationId: deleteUserIdentity
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - description: 外部アイデンティティID (idn_...)
          in: path
          name: identityId
          required: true
          schema:
            pattern: ^idn_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserIdentityDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の外部アイデンティティ削除
      tags:
        - User Sub-resources
  /users/{userId}/passkeys:
    get:
      description: 指定 User のパスキー一覧を返す (design.md §12.5)。`credential_id`・`public_key`・`sign_count` は返さない。
      operationId: listUserPasskeys
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserPasskeyListResponse"
          description: パスキーのページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User のパスキー一覧の取得
      tags:
        - User Sub-resources
  /users/{userId}/passkeys/{passkeyId}:
    delete:
      description: 指定パスキーを削除する。credential 変更に相当するため `user_passkeys:write` scope が必要 (design.md §25, §27.2)。If-Match による条件付き削除に対応 (§26.3)。
      operationId: deleteUserPasskey
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - description: パスキーID (psk_...)
          in: path
          name: passkeyId
          required: true
          schema:
            pattern: ^psk_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserPasskeyDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User のパスキー削除
      tags:
        - User Sub-resources
  /users/{userId}/sessions:
    delete:
      description: 指定 User の全セッションを失効する。`UserSecurityDO.securityVersion` が increment される (design.md §24.3)。If-Match による条件付き失効に対応 (§26.3)。
      operationId: revokeAllUserSessions
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserSessionsRevokeAllResponse"
          description: 失効結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の全セッション失効
      tags:
        - User Sub-resources
    get:
      description: 指定 User のセッション一覧を返す (design.md §12.4)。
      operationId: listUserSessions
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserSessionListResponse"
          description: セッションのページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User のセッション一覧の取得
      tags:
        - User Sub-resources
  /users/{userId}/sessions/{sessionId}:
    delete:
      description: 指定セッションを失効する (design.md §24)。If-Match による条件付き失効に対応 (§26.3)。
      operationId: revokeUserSession
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - description: セッションID (ses_...)
          in: path
          name: sessionId
          required: true
          schema:
            pattern: ^ses_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserSessionRevokeResponse"
          description: 失効結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User の個別セッション失効
      tags:
        - User Sub-resources
  /users/{userId}/unblock:
    post:
      description: User のブロックを解除する。リクエストボディはない。
      operationId: unblockUser
      parameters:
        - description: User ID (usr_...)
          in: path
          name: userId
          required: true
          schema:
            pattern: ^usr_[a-z2-7]{32}$
            type: string
        - in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserUnblockResponse"
          description: ブロック解除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: User のブロック解除
      tags:
        - Users
  /webhooks:
    get:
      description: "`environment_id` でスコープした Webhook Endpoint の一覧を返す (design.md §11.13, §26.2)。`secret_ciphertext` / `secret_iv` は返さない。"
      operationId: listWebhooks
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: 対象 Environment ID (env_...)
          in: query
          name: environment_id
          required: true
          schema:
            pattern: ^env_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookListResponse"
          description: Webhook Endpoint のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook Endpoint 一覧の取得
      tags:
        - Webhooks
    post:
      description: Webhook Endpoint を作成する (design.md §11.13, §29.4)。署名用の平文 secret はこのレスポンスで1回だけ表示される (§11.12 の display-once 規則)。
      operationId: createWebhook
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookCreateResponse"
          description: 作成された Webhook Endpoint (署名 secret を1回だけ表示)
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook Endpoint の作成
      tags:
        - Webhooks
  /webhooks/{webhookId}:
    delete:
      description: Webhook Endpoint を削除する。If-Match による条件付き削除に対応 (design.md §26.3)。
      operationId: deleteWebhook
      parameters:
        - description: Webhook Endpoint ID (whk_...)
          in: path
          name: webhookId
          required: true
          schema:
            pattern: ^whk_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeleteResponse"
          description: 削除結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook Endpoint の削除
      tags:
        - Webhooks
    patch:
      description: URL・購読イベント・status を更新する。If-Match による条件付き更新に対応 (design.md §26.3)。
      operationId: updateWebhook
      parameters:
        - description: Webhook Endpoint ID (whk_...)
          in: path
          name: webhookId
          required: true
          schema:
            pattern: ^whk_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
          description: 更新後の Webhook Endpoint
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook Endpoint の更新
      tags:
        - Webhooks
  /webhooks/{webhookId}/deliveries:
    get:
      description: 1つの Webhook Endpoint への delivery 履歴をカーソルページネーションで返す (design.md §27.3, §29.4, §10.10)。90日保持。status・occurred_at 範囲で絞り込み可能。request/response body・header・署名は含まない — status・attempt・response status code・duration のみ。
      operationId: listWebhookDeliveries
      parameters:
        - description: Webhook Endpoint ID (whk_...)
          in: path
          name: webhookId
          required: true
          schema:
            pattern: ^whk_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: delivery status で絞り込み
          in: query
          name: status
          required: false
          schema:
            enum:
              - pending
              - delivered
              - failed
              - exhausted
            type: string
        - description: この日時以降の delivery のみ (ISO 8601)
          in: query
          name: occurred_after
          required: false
          schema:
            format: date-time
            pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            type: string
        - description: この日時以前の delivery のみ (ISO 8601)
          in: query
          name: occurred_before
          required: false
          schema:
            format: date-time
            pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDeliveryListResponse"
          description: Webhook delivery 履歴のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook delivery 履歴の取得
      tags:
        - Webhooks
  /webhooks/{webhookId}/rotate-secret:
    post:
      description: 署名 secret をローテーションし、新しい平文 secret をこのレスポンスで1回だけ表示する (design.md §11.12 の display-once 規則)。リクエストボディはない。
      operationId: rotateWebhookSecret
      parameters:
        - description: Webhook Endpoint ID (whk_...)
          in: path
          name: webhookId
          required: true
          schema:
            pattern: ^whk_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookRotateSecretResponse"
          description: 新しい署名 secret (1回だけ表示)
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook 署名 secret のローテーション
      tags:
        - Webhooks
  /webhooks/{webhookId}/test:
    post:
      description: テストイベントを配送する (design.md §29.4)。2xx のみ成功。`event_type` 省略時は合成イベントを使い、指定時は購読中のイベントタイプでなければならない。
      operationId: testWebhook
      parameters:
        - description: Webhook Endpoint ID (whk_...)
          in: path
          name: webhookId
          required: true
          schema:
            pattern: ^whk_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookTestRequest"
        description: テストイベント指定 (任意)
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookTestResponse"
          description: 配送結果
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Webhook のテスト配送
      tags:
        - Webhooks
  /workspaces:
    get:
      description: Workspace のカーソルページネーション一覧を返す (design.md §11.1, §26.2)。
      operationId: listWorkspaces
      parameters:
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
        - description: ワークスペースステータスで絞り込み
          in: query
          name: status
          required: false
          schema:
            enum:
              - active
              - past_due
              - suspended
              - deleted
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceListResponse"
          description: Workspace のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Workspace 一覧の取得
      tags:
        - Workspaces
    post:
      description: Workspace を作成する (design.md §11.1)。`slug` 省略時は `name` からサーバが導出する。
      operationId: createWorkspace
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WorkspaceCreateRequest"
        description: 作成内容
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
          description: 作成された Workspace
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Workspace の作成
      tags:
        - Workspaces
  /workspaces/{workspaceId}:
    get:
      description: 単一 Workspace を返す (design.md §11.1)。ETag ヘッダを付与する。
      operationId: getWorkspace
      parameters:
        - description: Workspace ID (wsp_...)
          in: path
          name: workspaceId
          required: true
          schema:
            pattern: ^wsp_[a-z2-7]{32}$
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
          description: Workspace
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Workspace の取得
      tags:
        - Workspaces
    patch:
      description: name / slug を更新する。`status` の変更 (suspend 等) は課金・Owner 主導のライフサイクル遷移でありこの route では行えない (design.md §27.2)。If-Match による条件付き更新に対応 (§26.3)。
      operationId: updateWorkspace
      parameters:
        - description: Workspace ID (wsp_...)
          in: path
          name: workspaceId
          required: true
          schema:
            pattern: ^wsp_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/IfMatch"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WorkspaceUpdateRequest"
        description: 更新内容
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Workspace"
          description: 更新後の Workspace
          headers:
            ETag:
              $ref: "#/components/headers/ETag"
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "409":
          $ref: "#/components/responses/Conflict"
        "412":
          $ref: "#/components/responses/PreconditionFailed"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Workspace の更新
      tags:
        - Workspaces
  /workspaces/{workspaceId}/members:
    get:
      description: Workspace の member (design.md §11.2) をカーソルページネーションで返す (design.md §27.2 RBAC テーブル、§27.3 Security settings画面)。`platform_user_id`・`role`・`created_at`・`updated_at` のみで、credential は含まない。
      operationId: listWorkspaceMembers
      parameters:
        - description: Workspace ID (wsp_...)
          in: path
          name: workspaceId
          required: true
          schema:
            pattern: ^wsp_[a-z2-7]{32}$
            type: string
        - $ref: "#/components/parameters/Cursor"
        - $ref: "#/components/parameters/Limit"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkspaceMemberListResponse"
          description: Workspace member のページ
          headers:
            X-Request-Id:
              $ref: "#/components/headers/X-Request-Id"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "500":
          $ref: "#/components/responses/InternalServerError"
        default:
          $ref: "#/components/responses/DefaultError"
      summary: Workspace member 一覧の取得
      tags:
        - Workspaces
security:
  - ManagementApiKey: []
servers:
  - description: Management API base URL (design.md §26)
    url: https://api.example-auth.com/v1
tags:
  - description: Workspace (design.md §11.1)
    name: Workspaces
  - description: Project (design.md §11.3)
    name: Projects
  - description: Environment (design.md §11.4)
    name: Environments
  - description: Hosted Login の theme (design.md §23.2, §27.3)
    name: Themes
  - description: Environment ごとの management 設定
    name: Environment Settings
  - description: Client / リダイレクトURI / モバイルアプリ設定 (design.md §11.5-§11.8)
    name: Clients
  - description: ソーシャルプロバイダ Connection (design.md §11.10)
    name: Connections
  - description: Custom Domain (design.md §11.9)
    name: Domains
  - description: Management API key (design.md §11.12, §26.1)
    name: API Keys
  - description: User 管理 (design.md §12.1)
    name: Users
  - description: User の identities / passkeys / sessions (design.md §12.3-§12.5)
    name: User Sub-resources
  - description: ユーザー import / export ジョブ (design.md §26.2, §33.3)
    name: User Data Jobs
  - description: Webhook Endpoint (design.md §11.13, §29.4)
    name: Webhooks
  - description: 監査イベント (design.md §12.11)
    name: Audit Events
  - description: Impersonation session (design.md §27.4)
    name: Impersonation
  - description: MAU 使用量 (design.md §28)
    name: Usage
  - description: 課金 (design.md §28.5)
    name: Billing
