{
  "openapi": "3.0.0",
  "paths": {
    "/api/v1/config": {
      "get": {
        "operationId": "PublicConfigController_get_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicConfigDto"
                }
              }
            }
          }
        },
        "tags": ["config"]
      }
    },
    "/api/v1/users/me/devices": {
      "get": {
        "operationId": "DevicesController_list_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DeviceDto"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["notifications"]
      },
      "post": {
        "operationId": "DevicesController_register_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterDeviceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["notifications"]
      }
    },
    "/api/v1/users/me/devices/{deviceId}": {
      "delete": {
        "operationId": "DevicesController_remove_v1",
        "parameters": [
          {
            "name": "deviceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["notifications"]
      }
    },
    "/api/v1/push/config": {
      "get": {
        "operationId": "PushConfigController_get_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushConfigDto"
                }
              }
            }
          }
        },
        "tags": ["notifications"]
      }
    },
    "/api/v1/push/subscription-change": {
      "post": {
        "operationId": "PushConfigController_changeSubscription_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushSubscriptionChangeDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Always, whether or not a device matched"
          }
        },
        "tags": ["notifications"]
      }
    },
    "/api/v1/organizations/{organizationId}/notification-preferences": {
      "get": {
        "operationId": "PreferencesController_get_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Yours, in this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationPreferencesDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["notifications"]
      },
      "put": {
        "operationId": "PreferencesController_update_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateNotificationPreferencesDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationPreferencesDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["notifications"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/mutes": {
      "get": {
        "operationId": "MutesController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Your muted conversations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationMuteListDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["notifications"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/mute": {
      "put": {
        "operationId": "MutesController_set_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetConversationMuteDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationMuteStateDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["notifications"]
      }
    },
    "/api/v1/organizations/{organizationId}/audit-logs": {
      "get": {
        "operationId": "AuditLogsController_list_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Return items older than this id (the previous page’s nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["audit"]
      }
    },
    "/api/v1/health": {
      "get": {
        "operationId": "HealthController_readiness_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "All dependencies are up"
          },
          "503": {
            "description": "At least one dependency is down"
          }
        },
        "tags": ["health"]
      }
    },
    "/api/v1/health/live": {
      "get": {
        "operationId": "HealthController_liveness_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Process is alive"
          }
        },
        "tags": ["health"]
      }
    },
    "/api/v1/auth/register": {
      "post": {
        "operationId": "AuthController_register_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account + first organization created, signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Email already registered"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "operationId": "AuthController_login_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in (`tokens` + `user`), or, with two-factor authentication on, `mfaRequired: true` and an `mfaToken` for POST /auth/login/2fa (no tokens yet)",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AuthResponseDto"
                    },
                    {
                      "$ref": "#/components/schemas/MfaChallengeDto"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid email or password"
          },
          "403": {
            "description": "`code: account_disabled`"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/login/2fa": {
      "post": {
        "operationId": "AuthController_loginWithSecondFactor_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MfaLoginDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "`code: mfa_code_invalid` (wrong or used code; the token still works) or `code: mfa_token_invalid` (expired, used or too many wrong codes)"
          },
          "403": {
            "description": "`code: account_disabled`"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "operationId": "AuthController_refresh_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthTokensDto"
                }
              }
            }
          },
          "401": {
            "description": "Invalid, expired, revoked or reused refresh token"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/logout": {
      "post": {
        "operationId": "AuthController_logout_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/me": {
      "get": {
        "operationId": "AuthController_me_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponseDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/verify-email": {
      "post": {
        "operationId": "AuthController_verifyEmail_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/resend-verification": {
      "post": {
        "operationId": "AuthController_resendVerification_v1",
        "parameters": [],
        "responses": {
          "204": {
            "description": ""
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/forgot-password": {
      "post": {
        "operationId": "AuthController_forgotPassword_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForgotPasswordDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "If the account exists, a reset link was emailed"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/reset-password": {
      "post": {
        "operationId": "AuthController_resetPassword_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetPasswordDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Password changed; all sessions signed out"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/change-password": {
      "post": {
        "operationId": "AuthController_changePassword_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Password changed; other sessions signed out"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/sessions": {
      "get": {
        "operationId": "AuthController_sessions_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SessionDto"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/sessions/{sessionId}": {
      "delete": {
        "operationId": "AuthController_revokeSession_v1",
        "parameters": [
          {
            "name": "sessionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/2fa": {
      "get": {
        "operationId": "TwoFactorController_status_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TwoFactorStatusDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/2fa/setup": {
      "post": {
        "operationId": "TwoFactorController_setup_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TwoFactorPasswordDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TwoFactorSetupDto"
                }
              }
            }
          },
          "400": {
            "description": "Wrong password"
          },
          "409": {
            "description": "Already on"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/2fa/enable": {
      "post": {
        "operationId": "TwoFactorController_enable_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TwoFactorCodeDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecoveryCodesDto"
                }
              }
            }
          },
          "400": {
            "description": "`code: mfa_code_invalid`, or the setup expired (start again)"
          },
          "409": {
            "description": "Already on"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/2fa/disable": {
      "post": {
        "operationId": "TwoFactorController_disable_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DisableTwoFactorDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          },
          "400": {
            "description": "Wrong password, or `code: mfa_code_invalid`"
          },
          "409": {
            "description": "Not on"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/auth/2fa/recovery-codes": {
      "post": {
        "operationId": "TwoFactorController_regenerate_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TwoFactorCodeDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecoveryCodesDto"
                }
              }
            }
          },
          "400": {
            "description": "`code: mfa_code_invalid`"
          },
          "409": {
            "description": "Not on"
          },
          "429": {
            "description": "Rate limited; see Retry-After"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/users/me": {
      "patch": {
        "operationId": "UsersController_updateMe_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProfileDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["users"]
      },
      "delete": {
        "description": "Needs your password, plus `code` or `recoveryCode` when two-factor authentication is on. Deletes organizations where you are the only member (only with `deleteOwnedOrganizations: true`), leaves the others, revokes every session and deletes the account. Messages you sent stay with the organizations, shown as \"Deleted user\". Sends a confirmation email. Not available to staff \"login as customer\" sessions.",
        "operationId": "AccountDeletionController_deleteMe_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteAccountDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted; every session is revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedAccountDto"
                }
              }
            }
          },
          "400": {
            "description": "`code`: `password_invalid`, `two_factor_required` (send `code` or `recoveryCode`) or `mfa_code_invalid`"
          },
          "403": {
            "description": "`impersonation_forbidden`"
          },
          "409": {
            "description": "`sole_owner`: you are the only owner of organizations with other members. `owned_organizations`: you are the only member of organizations, resend with `deleteOwnedOrganizations: true`. `active_subscription`: one of those has a Stripe/PayPal subscription. `organizations` lists them",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDeletionConflictDto"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited, or too many wrong passwords"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Delete your account",
        "tags": ["users"]
      }
    },
    "/api/v1/organizations": {
      "post": {
        "operationId": "OrganizationsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new organization, with you as owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["organizations"]
      },
      "get": {
        "operationId": "OrganizationsController_list_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Organizations you belong to, with your role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MembershipDto"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["organizations"]
      }
    },
    "/api/v1/organizations/{organizationId}": {
      "get": {
        "operationId": "OrganizationController_get_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["organizations"]
      },
      "patch": {
        "operationId": "OrganizationController_update_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["organizations"]
      }
    },
    "/api/v1/organizations/{organizationId}/logo": {
      "put": {
        "operationId": "OrganizationLogoController_upload_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The image bytes",
          "content": {
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The organization with its new logoUrl",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationDto"
                }
              }
            }
          },
          "400": {
            "description": "Upload a PNG, JPEG or WebP image / This image could not be read. Upload a PNG, JPEG or WebP image of at most 25 megapixels"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "413": {
            "description": "Logos can be at most 2 MB"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["organizations"]
      },
      "delete": {
        "operationId": "OrganizationLogoController_remove_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The organization, logoUrl null",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["organizations"]
      },
      "get": {
        "operationId": "OrganizationLogoFileController_file_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "v",
            "required": true,
            "in": "query",
            "description": "The version from `logoUrl`",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The logo (image/png, image/jpeg or image/webp)"
          }
        },
        "tags": ["organizations"]
      }
    },
    "/api/v1/organizations/{organizationId}/members": {
      "get": {
        "operationId": "MembersController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MemberDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["members"]
      }
    },
    "/api/v1/organizations/{organizationId}/members/{memberId}": {
      "patch": {
        "operationId": "MembersController_changeRole_v1",
        "parameters": [
          {
            "name": "memberId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "Would leave the organization without an owner"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["members"]
      },
      "delete": {
        "operationId": "MembersController_remove_v1",
        "parameters": [
          {
            "name": "memberId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "Would leave the organization without an owner"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["members"]
      }
    },
    "/api/v1/organizations/{organizationId}/invitations": {
      "post": {
        "operationId": "InvitationsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvitationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invitation created and emailed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "Already a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["invitations"]
      },
      "get": {
        "operationId": "InvitationsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InvitationDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["invitations"]
      }
    },
    "/api/v1/organizations/{organizationId}/invitations/{invitationId}": {
      "delete": {
        "operationId": "InvitationsController_revoke_v1",
        "parameters": [
          {
            "name": "invitationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["invitations"]
      }
    },
    "/api/v1/invitations/{token}": {
      "get": {
        "operationId": "InvitationLinksController_preview_v1",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationPreviewDto"
                }
              }
            }
          }
        },
        "tags": ["invitations"]
      }
    },
    "/api/v1/invitations/accept": {
      "post": {
        "operationId": "InvitationLinksController_accept_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptInvitationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipDto"
                }
              }
            }
          },
          "410": {
            "description": "Invitation expired, revoked or already used"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["invitations"]
      }
    },
    "/api/v1/organizations/{organizationId}/teams": {
      "get": {
        "operationId": "TeamsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeamDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      },
      "post": {
        "operationId": "TeamsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTeamDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      }
    },
    "/api/v1/organizations/{organizationId}/teams/{teamId}": {
      "get": {
        "operationId": "TeamsController_get_v1",
        "parameters": [
          {
            "name": "teamId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      },
      "patch": {
        "operationId": "TeamsController_update_v1",
        "parameters": [
          {
            "name": "teamId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTeamDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      },
      "delete": {
        "operationId": "TeamsController_remove_v1",
        "parameters": [
          {
            "name": "teamId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      }
    },
    "/api/v1/organizations/{organizationId}/teams/{teamId}/members": {
      "put": {
        "operationId": "TeamsController_setMembers_v1",
        "parameters": [
          {
            "name": "teamId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetTeamMembersDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["teams"]
      }
    },
    "/api/v1/organizations/{organizationId}/agents": {
      "get": {
        "operationId": "AgentsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Members who can answer chats, with live status and load",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AgentDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["agents"]
      }
    },
    "/api/v1/organizations/{organizationId}/agents/me/status": {
      "put": {
        "operationId": "AgentsController_setStatus_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetStatusDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Only `online` agents receive automatically assigned chats"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["agents"]
      }
    },
    "/api/v1/organizations/{organizationId}/routing": {
      "get": {
        "operationId": "AgentsController_settings_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingSettingsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["agents"]
      },
      "patch": {
        "operationId": "AgentsController_updateSettings_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRoutingSettingsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoutingSettingsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["agents"]
      }
    },
    "/api/v1/organizations/{organizationId}/routing/queue": {
      "get": {
        "operationId": "AgentsController_queue_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Live chats against the plan's concurrent-chat limit, and waiting chats' places in line",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueSummaryDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["agents"]
      }
    },
    "/api/v1/organizations/{organizationId}/skills": {
      "get": {
        "operationId": "SkillsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SkillDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["skills"]
      },
      "post": {
        "operationId": "SkillsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveSkillDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["skills"]
      }
    },
    "/api/v1/organizations/{organizationId}/skills/{skillId}": {
      "patch": {
        "operationId": "SkillsController_rename_v1",
        "parameters": [
          {
            "name": "skillId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveSkillDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["skills"]
      },
      "delete": {
        "operationId": "SkillsController_remove_v1",
        "parameters": [
          {
            "name": "skillId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Members lose it; chats and websites that needed it no longer need a skill"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["skills"]
      }
    },
    "/api/v1/organizations/{organizationId}/members/{memberId}/skills": {
      "put": {
        "operationId": "SkillsController_setMemberSkills_v1",
        "parameters": [
          {
            "name": "memberId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetMemberSkillsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberSkillsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["skills"]
      }
    },
    "/api/v1/users/me/deletion": {
      "get": {
        "operationId": "AccountDeletionController_preview_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDeletionPreviewDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "What deleting your account would do (before asking for the password)",
        "tags": ["users"]
      }
    },
    "/api/v1/admin/step-up": {
      "post": {
        "operationId": "AdminController_createStepUp_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StepUpDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepUpResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Wrong password; with 2FA on, `code: two_factor_required` (no code) or `code: mfa_code_invalid`"
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "429": {
            "description": "Too many attempts (per IP and per account)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/audit-logs": {
      "get": {
        "operationId": "AdminController_auditLogs_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Return items older than this id (the previous page’s nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "step_up.verified",
                "step_up.failed",
                "organization.plan_set",
                "organization.plan_canceled",
                "organization.suspended",
                "organization.unsuspended",
                "organization.deleted",
                "user.email_verified",
                "user.signed_out",
                "user.disabled",
                "user.enabled",
                "user.password_reset_sent",
                "user.two_factor_reset",
                "user.account_deleted",
                "impersonation.started",
                "impersonation.ended",
                "queue.job_retried",
                "queue.failed_retried",
                "queue.job_removed",
                "queue.paused",
                "queue.resumed",
                "queue.dead_letter_requeued",
                "announcement.created",
                "announcement.updated",
                "announcement.deleted",
                "settings.updated",
                "settings.test_email_sent",
                "settings.secrets_resealed",
                "plan.updated",
                "plan.deleted",
                "organization.limits_set",
                "organization.limits_cleared",
                "organization.price_set",
                "organization.price_cleared"
              ]
            }
          },
          {
            "name": "actor",
            "required": false,
            "in": "query",
            "description": "Part of the admin’s email, or their exact `usr_…` id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetType",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["organization", "user", "session", "setting", "plan", "system"]
            }
          },
          {
            "name": "targetId",
            "required": false,
            "in": "query",
            "description": "`org_…`, `usr_…`, `ses_…` or a settings key",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "From this moment (inclusive)",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Before this moment",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAuditLogPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations": {
      "get": {
        "operationId": "AdminController_list_v1",
        "parameters": [
          {
            "name": "query",
            "required": false,
            "in": "query",
            "description": "Part of the name, slug or owner email, or an exact `org_…` id. Empty: all",
            "schema": {
              "example": "acme",
              "type": "string"
            }
          },
          {
            "name": "plan",
            "required": false,
            "in": "query",
            "description": "The plan in force now",
            "schema": {
              "type": "string",
              "enum": ["free", "starter", "business", "pro", "enterprise"]
            }
          },
          {
            "name": "provider",
            "required": false,
            "in": "query",
            "description": "`none`: no subscription",
            "schema": {
              "type": "string",
              "enum": ["stripe", "paypal", "manual", "none"]
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Subscription status; `none`",
            "schema": {
              "type": "string",
              "enum": ["trialing", "active", "past_due", "canceled", "incomplete", "none"]
            }
          },
          {
            "name": "suspended",
            "required": false,
            "in": "query",
            "description": "Only suspended (or not suspended)",
            "schema": {
              "type": "string",
              "enum": ["true", "false"]
            }
          },
          {
            "name": "includeTest",
            "required": false,
            "in": "query",
            "description": "Include test and e2e organizations (owner on a test domain)",
            "schema": {
              "default": "false",
              "type": "string",
              "enum": ["true", "false"]
            }
          },
          {
            "name": "sort",
            "required": false,
            "in": "query",
            "schema": {
              "default": "created_desc",
              "type": "string",
              "enum": ["created_desc", "created_asc", "name", "members", "conversations", "storage"]
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationListDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}/subscription": {
      "put": {
        "operationId": "AdminController_setPlan_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetManualPlanDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "409": {
            "description": "The organization pays through Stripe or PayPal"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminController_cancelPlan_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/overview": {
      "get": {
        "operationId": "AdminController_overview_v1",
        "parameters": [
          {
            "name": "includeTest",
            "required": false,
            "in": "query",
            "schema": {
              "default": "false",
              "type": "string",
              "enum": ["true", "false"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOverviewDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}": {
      "get": {
        "operationId": "AdminController_detail_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such organization"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminController_remove_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedOrganizationDto"
                }
              }
            }
          },
          "400": {
            "description": "The slug does not match"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "An active Stripe or PayPal subscription"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}/suspend": {
      "post": {
        "operationId": "AdminController_suspend_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuspendOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "Already suspended"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}/unsuspend": {
      "post": {
        "operationId": "AdminController_unsuspend_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnsuspendOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminOrganizationDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "Not suspended"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}/price": {
      "get": {
        "operationId": "AdminController_price_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationPriceResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "put": {
        "operationId": "AdminController_setPrice_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetOrganizationPriceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationPriceResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Not a Stripe price or PayPal plan id"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminController_clearPrice_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationPriceResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "404": {
            "description": "No price of its own"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users": {
      "get": {
        "operationId": "AdminUsersController_list_v1",
        "parameters": [
          {
            "name": "query",
            "required": false,
            "in": "query",
            "description": "Part of the email or name, or an exact `usr_…` id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserListDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such user"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}": {
      "get": {
        "operationId": "AdminUsersController_detail_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such user"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/verify-email": {
      "post": {
        "operationId": "AdminUsersController_verifyEmail_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such user"
          },
          "409": {
            "description": "Already verified"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/sign-out": {
      "post": {
        "operationId": "AdminUsersController_signOut_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignedOutDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such user"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/disable": {
      "post": {
        "operationId": "AdminUsersController_disable_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DisableUserDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserDto"
                }
              }
            }
          },
          "400": {
            "description": "Yourself"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "404": {
            "description": "No such user"
          },
          "409": {
            "description": "Already disabled"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/enable": {
      "post": {
        "operationId": "AdminUsersController_enable_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "404": {
            "description": "No such user"
          },
          "409": {
            "description": "Not disabled"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/two-factor/reset": {
      "post": {
        "operationId": "AdminUsersController_resetTwoFactor_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserDto"
                }
              }
            }
          },
          "400": {
            "description": "Yourself"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "404": {
            "description": "No such user"
          },
          "409": {
            "description": "Two-factor authentication is not on"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/users/{userId}/password-reset": {
      "post": {
        "operationId": "AdminUsersController_passwordReset_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Reset email queued"
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "No such user"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/impersonate": {
      "post": {
        "operationId": "ImpersonationController_start_v1",
        "parameters": [
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartImpersonationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartImpersonationResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "Suspended organization, no owner, or a disabled owner"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/auth/impersonation/end": {
      "post": {
        "operationId": "ImpersonationEndController_end_v1",
        "parameters": [],
        "responses": {
          "204": {
            "description": "Session revoked; audited as ended"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["auth"]
      }
    },
    "/api/v1/admin/impersonations": {
      "get": {
        "operationId": "AdminImpersonationsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": false,
            "in": "query",
            "description": "Only this organization",
            "schema": {
              "example": "org_…",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminImpersonationSessionDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/impersonations/{sessionId}/end": {
      "post": {
        "operationId": "AdminImpersonationsController_end_v1",
        "parameters": [
          {
            "name": "sessionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Ended"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "404": {
            "description": "No live impersonation session with this id"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/billing/plans": {
      "get": {
        "operationId": "BillingPublicController_plans_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanCatalogDto"
                }
              }
            }
          }
        },
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing": {
      "get": {
        "operationId": "BillingController_overview_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Plan in effect, limits, usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingOverviewDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing/checkout": {
      "post": {
        "operationId": "BillingController_checkout_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Send the owner to the provider to pay",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedirectDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing/portal": {
      "post": {
        "operationId": "BillingController_portal_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedirectDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing/change": {
      "post": {
        "operationId": "BillingController_change_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePlanDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "url is set when the provider must confirm (PayPal)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedirectDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing/cancel": {
      "post": {
        "operationId": "BillingController_cancel_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/billing/invoices": {
      "get": {
        "operationId": "BillingController_invoices_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InvoiceDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["billing"]
      }
    },
    "/api/v1/organizations/{organizationId}/websites": {
      "get": {
        "operationId": "WebsitesController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebsiteDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      },
      "post": {
        "operationId": "WebsitesController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebsiteDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebsiteDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      }
    },
    "/api/v1/organizations/{organizationId}/websites/{websiteId}": {
      "get": {
        "operationId": "WebsitesController_get_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebsiteDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      },
      "patch": {
        "operationId": "WebsitesController_update_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebsiteDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebsiteDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      },
      "delete": {
        "operationId": "WebsitesController_remove_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted; the widget stops loading on the site"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      }
    },
    "/api/v1/organizations/{organizationId}/websites/{websiteId}/regenerate-key": {
      "post": {
        "operationId": "WebsitesController_regenerateKey_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "New site key; update the snippet on your site",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebsiteDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      }
    },
    "/api/v1/organizations/{organizationId}/websites/{websiteId}/identity-secret": {
      "get": {
        "operationId": "WebsitesController_identitySecret_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Never returns the secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentitySecretStatusDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      },
      "post": {
        "operationId": "WebsitesController_rotateIdentitySecret_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Creates or rotates the secret; it is shown only in this response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentitySecretDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      },
      "delete": {
        "operationId": "WebsitesController_disableIdentitySecret_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Identity verification off; hashes are rejected"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["websites"]
      }
    },
    "/api/v1/timezones": {
      "get": {
        "operationId": "TimeZonesController_list_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeZoneDto"
                  }
                }
              }
            }
          }
        },
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/config": {
      "get": {
        "operationId": "WidgetController_config_v1",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "query",
            "schema": {
              "example": "zc_8kQ2…",
              "type": "string"
            }
          },
          {
            "name": "host",
            "required": true,
            "in": "query",
            "description": "Origin of the page embedding the widget",
            "schema": {
              "example": "https://example.com",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetConfigDto"
                }
              }
            }
          },
          "403": {
            "description": "Host is not an allowed domain for this website"
          },
          "404": {
            "description": "Unknown site key"
          }
        },
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/sessions": {
      "post": {
        "operationId": "WidgetController_session_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWidgetSessionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetSessionDto"
                }
              }
            }
          },
          "403": {
            "description": "Host is not an allowed domain for this website, or the website's country rules hide the widget from this visitor"
          },
          "404": {
            "description": "Unknown site key"
          },
          "429": {
            "description": "Per IP or per website limit reached"
          }
        },
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/sessions/refresh": {
      "post": {
        "operationId": "WidgetController_refresh_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Same visitor, new token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetSessionDto"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or already expired visitor token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/me": {
      "get": {
        "operationId": "WidgetController_me_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetVisitorDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/identify": {
      "post": {
        "operationId": "WidgetController_identify_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdentifyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session for the resulting visitor: switch to this token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetSessionDto"
                }
              }
            }
          },
          "400": {
            "description": "id without hash (or the reverse), or verification is off for the website"
          },
          "403": {
            "description": "Invalid hash, or unverified details for an already verified visitor"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations": {
      "get": {
        "operationId": "ConversationsController_list_v1",
        "parameters": [
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "`active` = new, open, pending, waiting",
            "schema": {
              "default": "active",
              "type": "string",
              "enum": [
                "active",
                "all",
                "new",
                "open",
                "pending",
                "waiting",
                "resolved",
                "closed",
                "spam"
              ]
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assignee",
            "required": false,
            "in": "query",
            "description": "`me`: assigned to you, or you take part as a co-agent (`participant`)",
            "schema": {
              "default": "any",
              "type": "string",
              "enum": ["me", "unassigned", "any"]
            }
          },
          {
            "name": "skillId",
            "required": false,
            "in": "query",
            "description": "Chats that need this skill",
            "schema": {
              "example": "skl_…",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "tag_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "vis_…",
              "type": "string"
            }
          },
          {
            "name": "priority",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["low", "normal", "high", "urgent"]
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Created at or after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Created at or before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Visitor name/email contains it, or a message matches it (full-text)",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 30,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Most recent activity first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/counts": {
      "get": {
        "operationId": "ConversationsController_counts_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationCountsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}": {
      "get": {
        "operationId": "ConversationsController_get_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      },
      "patch": {
        "operationId": "ConversationsController_update_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConversationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolve, close, reopen or set priority",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/messages": {
      "get": {
        "operationId": "ConversationsController_messages_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "required": false,
            "in": "query",
            "description": "Messages after this message id (sync after reconnect), ascending",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Messages before this message id (scroll back)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessagePageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      },
      "post": {
        "operationId": "ConversationsController_send_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSendMessageDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Idempotent per clientMessageId",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatMessageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "Conversation is closed"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/tags": {
      "put": {
        "operationId": "ConversationsController_setTags_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetTagsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replaces the conversation’s tags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/attachments": {
      "post": {
        "operationId": "ConversationsController_createAttachment_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAttachmentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentUploadDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/read": {
      "post": {
        "operationId": "ConversationsController_read_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/assign": {
      "post": {
        "operationId": "ConversationsController_assign_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/transfer": {
      "post": {
        "operationId": "ConversationsController_transfer_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/search/messages": {
      "get": {
        "operationId": "SearchController_messages_v1",
        "parameters": [
          {
            "name": "q",
            "required": true,
            "in": "query",
            "schema": {
              "minLength": 1,
              "maxLength": 200,
              "example": "refund \"order 1234\"",
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 50,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageSearchPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}/conversations": {
      "post": {
        "operationId": "VisitorConversationsController_start_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The sent message; `conversationId` is the (new or active) conversation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatMessageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/widget/conversations": {
      "post": {
        "operationId": "WidgetChatController_start_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartConversationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartConversationResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/current": {
      "get": {
        "operationId": "WidgetChatController_current_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The active conversation, or null",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorConversationDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/messages": {
      "get": {
        "operationId": "WidgetChatController_messages_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "required": false,
            "in": "query",
            "description": "Messages after this message id (sync after reconnect), ascending",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Messages before this message id (scroll back)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessagePageDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      },
      "post": {
        "operationId": "WidgetChatController_send_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatMessageDto"
                }
              }
            }
          },
          "409": {
            "description": "Conversation is closed; start a new one"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/read": {
      "post": {
        "operationId": "WidgetChatController_read_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/close": {
      "post": {
        "operationId": "WidgetChatController_close_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The conversation, now closed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorConversationDto"
                }
              }
            }
          },
          "404": {
            "description": "Not this visitor's conversation"
          },
          "429": {
            "description": "Per IP or per visitor limit reached"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/attachments": {
      "post": {
        "operationId": "WidgetChatController_createAttachment_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAttachmentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentUploadDto"
                }
              }
            }
          },
          "403": {
            "description": "File uploads are turned off for this website"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/attachments": {
      "post": {
        "operationId": "WidgetAttachmentsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAttachmentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentUploadDto"
                }
              }
            }
          },
          "400": {
            "description": "File type not allowed"
          },
          "403": {
            "description": "File uploads are turned off for this website"
          },
          "413": {
            "description": "Larger than attachmentMaxBytes"
          },
          "429": {
            "description": "Per IP or per visitor limit reached"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/participants": {
      "post": {
        "operationId": "ParticipantsController_add_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddParticipantDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/participants/{userId}": {
      "delete": {
        "operationId": "ParticipantsController_remove_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/monitor": {
      "post": {
        "operationId": "ParticipantsController_monitor_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/join": {
      "post": {
        "operationId": "ParticipantsController_join_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["conversations"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/live": {
      "get": {
        "operationId": "VisitorsController_live_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 500,
              "default": 200,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveVisitorsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors": {
      "get": {
        "operationId": "VisitorsController_list_v1",
        "parameters": [
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Name, email or external id contains this",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "name": "filter",
            "required": false,
            "in": "query",
            "schema": {
              "default": "any",
              "type": "string",
              "enum": ["any", "online", "offline", "verified", "identified"]
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "All visitors, most recently seen first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}": {
      "get": {
        "operationId": "VisitorsController_profile_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorProfileDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      },
      "delete": {
        "operationId": "PrivacyController_erase_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}/journey": {
      "get": {
        "operationId": "VisitorsController_journey_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "visitId",
            "required": false,
            "in": "query",
            "description": "Defaults to the latest visit",
            "schema": {
              "example": "vst_…",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      }
    },
    "/api/v1/widget/pageviews": {
      "post": {
        "operationId": "WidgetTrackingController_pageview_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageviewDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Recorded; agents watching live visitors are updated"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/events": {
      "post": {
        "operationId": "WidgetTrackingController_event_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackEventDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Custom event from ZebChat.track()"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/organizations/{organizationId}/tags": {
      "get": {
        "operationId": "TagsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      },
      "post": {
        "operationId": "TagsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTagDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      }
    },
    "/api/v1/organizations/{organizationId}/tags/{tagId}": {
      "patch": {
        "operationId": "TagsController_update_v1",
        "parameters": [
          {
            "name": "tagId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTagDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      },
      "delete": {
        "operationId": "TagsController_remove_v1",
        "parameters": [
          {
            "name": "tagId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Also removes it from every conversation and visitor"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}/tags": {
      "get": {
        "operationId": "TagsController_visitorTags_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      },
      "put": {
        "operationId": "TagsController_setVisitorTags_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetTagsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replaces the visitor’s tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["tags"]
      }
    },
    "/api/v1/widget/visitor/tags": {
      "post": {
        "operationId": "WidgetTagsController_add_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VisitorTagNamesDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Adds tags (by name) to the visitor; unknown names are created"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/consent": {
      "post": {
        "operationId": "WidgetConsentController_record_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WidgetConsentRequestDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Logged (nothing is logged while consent handling is off)"
          },
          "400": {
            "description": "Unknown decision or source, or `gpc` mixed up"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/organizations/{organizationId}/consent-log": {
      "get": {
        "operationId": "ConsentLogController_list_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "vis_…",
              "type": "string"
            }
          },
          {
            "name": "decision",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["accepted", "necessary_only", "opt_out", "gpc", "withdrawn"]
            }
          },
          {
            "name": "purpose",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["storage", "privacy_policy"]
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Logged at or after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Logged before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Entries older than this id (the previous nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentLogPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["privacy"]
      }
    },
    "/api/v1/organizations/{organizationId}/consent-log/export": {
      "get": {
        "operationId": "ConsentLogController_export_v1",
        "parameters": [
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "vis_…",
              "type": "string"
            }
          },
          {
            "name": "decision",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["accepted", "necessary_only", "opt_out", "gpc", "withdrawn"]
            }
          },
          {
            "name": "purpose",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["storage", "privacy_policy"]
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "Logged at or after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Logged before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV with a header row",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["privacy"]
      }
    },
    "/api/v1/organizations/{organizationId}/canned-responses": {
      "get": {
        "operationId": "CannedResponsesController_list_v1",
        "parameters": [
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Matches the shortcut (prefix) or the title/body (contains)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sorted by shortcut",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CannedResponseDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["canned-responses"]
      },
      "post": {
        "operationId": "CannedResponsesController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCannedResponseDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CannedResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["canned-responses"]
      }
    },
    "/api/v1/organizations/{organizationId}/canned-responses/{cannedId}": {
      "patch": {
        "operationId": "CannedResponsesController_update_v1",
        "parameters": [
          {
            "name": "cannedId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCannedResponseDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CannedResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["canned-responses"]
      },
      "delete": {
        "operationId": "CannedResponsesController_remove_v1",
        "parameters": [
          {
            "name": "cannedId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["canned-responses"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}/export": {
      "get": {
        "operationId": "PrivacyController_export_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Visitor, tags, consent log entries, visits with pageviews/events, conversations with messages"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["visitors"]
      }
    },
    "/api/v1/avatars/presets": {
      "get": {
        "operationId": "AvatarsController_presets_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The built-in avatar set",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AvatarDto"
                  }
                }
              }
            }
          }
        },
        "tags": ["avatars"]
      }
    },
    "/api/v1/avatars/presets/{file}": {
      "get": {
        "operationId": "AvatarsController_presetFile_v1",
        "parameters": [
          {
            "name": "file",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": ["avatars"]
      }
    },
    "/api/v1/avatars": {
      "post": {
        "operationId": "AvatarsController_upload_v1",
        "parameters": [],
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadedAvatarDto"
                }
              }
            }
          }
        },
        "tags": ["avatars"]
      }
    },
    "/api/v1/avatars/u/{userId}/{avatarId}": {
      "get": {
        "operationId": "AvatarsController_uploaded_v1",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "avatarId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": ["avatars"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/rating": {
      "get": {
        "operationId": "WidgetRatingsController_get_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rating, or null (empty body)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorRatingDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      },
      "post": {
        "operationId": "WidgetRatingsController_rate_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RateConversationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisitorRatingDto"
                }
              }
            }
          },
          "403": {
            "description": "Ratings are turned off for this website"
          },
          "409": {
            "description": "The conversation has not ended yet, or the rating is locked (after 24 h)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/widget/conversations/{conversationId}/transcript": {
      "post": {
        "operationId": "WidgetTranscriptsController_send_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendTranscriptDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The email is queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptSentDto"
                }
              }
            }
          },
          "400": {
            "description": "No email sent and none saved for the visitor"
          },
          "403": {
            "description": "Transcripts are off for the website, or a verified visitor asked for another address"
          },
          "404": {
            "description": "Not this visitor's conversation"
          },
          "409": {
            "description": "The chat has no messages yet"
          },
          "429": {
            "description": "Per IP, visitor or organization limit, or one per chat every 10 minutes"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["widget"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/overview": {
      "get": {
        "operationId": "AnalyticsController_overview_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsOverviewDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/agents": {
      "get": {
        "operationId": "AnalyticsController_agents_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentAnalyticsDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/feedback": {
      "get": {
        "operationId": "FeedbackController_report_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "userId",
            "required": false,
            "in": "query",
            "description": "Only ratings counted for this agent (assigned when the visitor rated)",
            "schema": {
              "example": "usr_…",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackReportDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/feedback/comments": {
      "get": {
        "operationId": "FeedbackController_comments_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "userId",
            "required": false,
            "in": "query",
            "description": "Only ratings counted for this agent (assigned when the visitor rated)",
            "schema": {
              "example": "usr_…",
              "type": "string"
            }
          },
          {
            "name": "ratings",
            "required": false,
            "in": "query",
            "description": "Only these star ratings (comma-separated)",
            "schema": {
              "example": "1,2",
              "type": "string"
            }
          },
          {
            "name": "withComment",
            "required": false,
            "in": "query",
            "description": "Only ratings with a comment",
            "schema": {
              "default": true,
              "type": "boolean"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Newest first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackCommentPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/feedback/ai": {
      "get": {
        "operationId": "FeedbackController_ai_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "rating",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["up", "down"]
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agents' votes on AI replies, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiFeedbackPageDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/feedback/export": {
      "get": {
        "operationId": "FeedbackController_export_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "userId",
            "required": false,
            "in": "query",
            "description": "Only ratings counted for this agent (assigned when the visitor rated)",
            "schema": {
              "example": "usr_…",
              "type": "string"
            }
          },
          {
            "name": "ratings",
            "required": false,
            "in": "query",
            "schema": {
              "example": "1,2",
              "type": "string"
            }
          },
          {
            "name": "withComment",
            "required": false,
            "in": "query",
            "description": "Only ratings with a comment",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV (UTF-8 with BOM) of the ratings in the range"
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/advanced": {
      "get": {
        "operationId": "AdvancedAnalyticsController_report_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Rows per source, country and landing-page breakdown before the \"other\" row",
            "schema": {
              "minimum": 1,
              "maximum": 50,
              "default": 10,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdvancedAnalyticsDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "402": {
            "description": "The plan does not include advanced analytics (`feature: advancedAnalytics`)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/analytics/advanced/export": {
      "get": {
        "operationId": "AdvancedAnalyticsController_export_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (YYYY-MM-DD) in the organization's time zone. Default: 6 days before `to`",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive (default today in the organization's time zone). At most 366 days in all",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "teamId",
            "required": false,
            "in": "query",
            "description": "Only this team's current members",
            "schema": {
              "example": "team_…",
              "type": "string"
            }
          },
          {
            "name": "websiteId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "web_…",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Rows per source, country and landing-page breakdown before the \"other\" row",
            "schema": {
              "minimum": 1,
              "maximum": 50,
              "default": 10,
              "type": "number"
            }
          },
          {
            "name": "type",
            "required": true,
            "in": "query",
            "description": "`conversations`: one row per conversation (oldest first, at most 100,000); `breakdowns`: every breakdown table",
            "schema": {
              "type": "string",
              "enum": ["conversations", "breakdowns"]
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV (UTF-8 with BOM). `X-Export-Truncated: true` when the range holds more than 100,000 conversations (a last line says so)"
          },
          "400": {
            "description": "Invalid dates, range longer than 366 days, or bad id"
          },
          "402": {
            "description": "The plan does not include advanced analytics (`feature: advancedAnalytics`)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["analytics"]
      }
    },
    "/api/v1/organizations/{organizationId}/api-keys": {
      "get": {
        "operationId": "ApiKeysController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Newest first, revoked and expired included",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKeyDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["api-keys"]
      },
      "post": {
        "operationId": "ApiKeysController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The only response with the key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedApiKeyDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the API"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["api-keys"]
      }
    },
    "/api/v1/organizations/{organizationId}/api-keys/{apiKeyId}": {
      "delete": {
        "operationId": "ApiKeysController_revoke_v1",
        "parameters": [
          {
            "name": "apiKeyId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked: the key stops working immediately"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["api-keys"]
      }
    },
    "/api/v1/organizations/{organizationId}/integrations": {
      "get": {
        "operationId": "IntegrationsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IntegrationDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["integrations"]
      },
      "post": {
        "operationId": "IntegrationsController_connect_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectIntegrationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["integrations"]
      }
    },
    "/api/v1/organizations/{organizationId}/integrations/{integrationId}": {
      "patch": {
        "operationId": "IntegrationsController_update_v1",
        "parameters": [
          {
            "name": "integrationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateIntegrationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["integrations"]
      },
      "delete": {
        "operationId": "IntegrationsController_disconnect_v1",
        "parameters": [
          {
            "name": "integrationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["integrations"]
      }
    },
    "/api/v1/organizations/{organizationId}/integrations/{integrationId}/test": {
      "post": {
        "operationId": "IntegrationsController_test_v1",
        "parameters": [
          {
            "name": "integrationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Queues a sample conversation, or re-checks Shopify"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["integrations"]
      }
    },
    "/api/v1/integrations/shopify/widget.js": {
      "get": {
        "operationId": "ShopifyPublicController_widget_v1",
        "parameters": [
          {
            "name": "shop",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": ["integrations"]
      }
    },
    "/api/v1/integrations/shopify/webhooks": {
      "post": {
        "operationId": "ShopifyPublicController_webhook_v1",
        "parameters": [],
        "responses": {
          "204": {
            "description": ""
          }
        },
        "tags": ["integrations"]
      }
    },
    "/api/v1/integrations/bigcommerce/webhooks": {
      "post": {
        "operationId": "BigcommercePublicController_webhook_v1",
        "parameters": [],
        "responses": {
          "204": {
            "description": ""
          }
        },
        "tags": ["integrations"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks": {
      "get": {
        "operationId": "WebhooksController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookEndpointDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      },
      "post": {
        "operationId": "WebhooksController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Includes the secret, once",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedWebhookEndpointDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the API"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}": {
      "get": {
        "operationId": "WebhooksController_get_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      },
      "patch": {
        "operationId": "WebhooksController_update_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      },
      "delete": {
        "operationId": "WebhooksController_remove_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted with its delivery log"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}/rotate-secret": {
      "post": {
        "operationId": "WebhooksController_rotateSecret_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecretDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}/test": {
      "post": {
        "operationId": "WebhooksController_test_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "A `webhook.test` delivery",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "The endpoint is turned off"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}/deliveries": {
      "get": {
        "operationId": "WebhooksController_deliveries_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Return items older than this id (the previous page’s nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["pending", "succeeded", "failed"]
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}/deliveries/{deliveryId}": {
      "get": {
        "operationId": "WebhooksController_delivery_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/organizations/{organizationId}/webhooks/{webhookId}/deliveries/{deliveryId}/replay": {
      "post": {
        "operationId": "WebhooksController_replay_v1",
        "parameters": [
          {
            "name": "webhookId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "A new delivery of the same event (same id and body)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "The endpoint is turned off"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["webhooks"]
      }
    },
    "/api/v1/admin/settings": {
      "get": {
        "operationId": "AdminSettingsController_get_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformSettingsResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/encryption": {
      "get": {
        "operationId": "AdminSettingsController_encryption_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyStatusDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/encryption/reseal": {
      "post": {
        "operationId": "AdminSettingsController_reseal_v1",
        "parameters": [
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResealSecretsResultDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "503": {
            "description": "SETTINGS_ENCRYPTION_KEY is not set"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/{group}": {
      "put": {
        "operationId": "AdminSettingsController_update_v1",
        "parameters": [
          {
            "name": "group",
            "required": true,
            "in": "path",
            "schema": {
              "enum": [
                "smtp",
                "branding",
                "stripe",
                "paypal",
                "push",
                "turnstile",
                "maps",
                "general"
              ],
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "example": {
                  "host": "smtp.example.com",
                  "port": 587,
                  "security": "starttls",
                  "password": "…"
                },
                "description": "Fields of the group (see SETTING_FIELDS in @zebchat/types); null clears a saved value. Email (smtp): provider smtp|zeptomail; ZeptoMail uses zeptomailHost (a Zoho API host), zeptomailToken (write-only; the \"Zoho-enczapikey \" prefix is optional) and bounceAddress"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformSettingsResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or unknown fields (one message per field)"
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "503": {
            "description": "SETTINGS_ENCRYPTION_KEY missing for a secret"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/smtp/test-email": {
      "post": {
        "operationId": "AdminSettingsController_testEmail_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "ok: true with the provider used (and ZeptoMail’s request id); ok: false with the refusal (e.g. “ZeptoMail refused the email: the API key is invalid … [HTTP 401 TM_4001/SERR_157]”)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsTestResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/branding/preview": {
      "post": {
        "operationId": "AdminSettingsController_previewEmail_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "template": {
                    "type": "string",
                    "enum": [
                      "chat-alert",
                      "verify-email",
                      "reset-password",
                      "invitation",
                      "chat-transcript",
                      "webhook-disabled",
                      "ai-key-failed",
                      "organization-suspended",
                      "organization-unsuspended",
                      "two-factor-enabled",
                      "two-factor-disabled",
                      "two-factor-reset",
                      "two-factor-recovery-code-used",
                      "account-deleted"
                    ],
                    "default": "chat-alert"
                  },
                  "values": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Unsaved fields of the branding group (null = what applies once the saved value is removed)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailPreviewDto"
                }
              }
            }
          },
          "400": {
            "description": "Unknown template, or invalid or unknown fields"
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/{group}/test": {
      "post": {
        "operationId": "AdminSettingsController_testConnection_v1",
        "parameters": [
          {
            "name": "group",
            "required": true,
            "in": "path",
            "schema": {
              "enum": ["stripe", "paypal"],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsTestResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/settings/push/vapid-keys": {
      "post": {
        "operationId": "AdminSettingsController_generateVapid_v1",
        "parameters": [
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformSettingsResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/plans": {
      "get": {
        "operationId": "AdminPlansController_list_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminPlanListDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/plans/{code}/impact": {
      "get": {
        "operationId": "AdminPlansController_impact_v1",
        "parameters": [
          {
            "name": "code",
            "required": true,
            "in": "path",
            "schema": {
              "enum": ["free", "starter", "business", "pro", "enterprise"],
              "type": "string"
            }
          },
          {
            "name": "agents",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "websites",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "concurrentChats",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "storageBytes",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "maxRetentionDays",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanImpactDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/plans/{code}": {
      "put": {
        "operationId": "AdminPlansController_update_v1",
        "parameters": [
          {
            "name": "code",
            "required": true,
            "in": "path",
            "schema": {
              "enum": ["free", "starter", "business", "pro", "enterprise"],
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePlanDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminPlanDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "Deactivating the default plan for new organizations"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminPlansController_remove_v1",
        "parameters": [
          {
            "name": "code",
            "required": true,
            "in": "path",
            "schema": {
              "enum": ["free", "starter", "business", "pro", "enterprise"],
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          },
          "409": {
            "description": "Organizations are on this plan"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/organizations/{organizationId}/limits": {
      "get": {
        "operationId": "AdminOrganizationLimitsController_get_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationLimitsDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "put": {
        "operationId": "AdminOrganizationLimitsController_set_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetOrganizationLimitsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationLimitsDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminOrganizationLimitsController_clear_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationLimitsDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/health": {
      "get": {
        "operationId": "SystemController_overview_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemHealthDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues": {
      "get": {
        "operationId": "SystemController_queueList_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueListDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/failed": {
      "get": {
        "operationId": "SystemController_failed_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "start",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FailedJobPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown queue"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/jobs/{jobId}/retry": {
      "post": {
        "operationId": "SystemController_retry_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "jobId",
            "required": true,
            "in": "path",
            "description": "BullMQ job id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown queue or job"
          },
          "409": {
            "description": "The job is not failed"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/jobs/{jobId}": {
      "delete": {
        "operationId": "SystemController_remove_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "jobId",
            "required": true,
            "in": "path",
            "description": "BullMQ job id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown queue or job"
          },
          "409": {
            "description": "The job is running"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/retry-failed": {
      "post": {
        "operationId": "SystemController_retryAll_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/pause": {
      "post": {
        "operationId": "SystemController_pause_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/queues/{queue}/resume": {
      "post": {
        "operationId": "SystemController_resume_v1",
        "parameters": [
          {
            "name": "queue",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string",
              "enum": [
                "push",
                "system",
                "email",
                "analytics",
                "media",
                "webhooks",
                "knowledge",
                "ai",
                "ai-results",
                "contacts",
                "integrations",
                "dead-letter"
              ]
            }
          },
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/dead-letters": {
      "get": {
        "operationId": "SystemController_deadLetters_v1",
        "parameters": [
          {
            "name": "start",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 0,
              "default": 0,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeadLetterPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/dead-letters/{jobId}/requeue": {
      "post": {
        "operationId": "SystemController_requeue_v1",
        "parameters": [
          {
            "name": "jobId",
            "required": true,
            "in": "path",
            "description": "BullMQ job id in the dead-letter queue",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown dead letter"
          },
          "409": {
            "description": "Malformed, or the original queue is unknown"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/dead-letters/requeue-all": {
      "post": {
        "operationId": "SystemController_requeueAll_v1",
        "parameters": [
          {
            "name": "X-Step-Up",
            "in": "header",
            "description": "Step-up token from POST /api/v1/admin/step-up (valid 10 minutes, this session only)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueActionResultDto"
                }
              }
            }
          },
          "403": {
            "description": "`code: step_up_required`: missing, wrong or expired step-up token"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/deliveries/email": {
      "get": {
        "operationId": "SystemController_email_v1",
        "parameters": [
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["sent", "failed", "retrying", "skipped"]
            }
          },
          {
            "name": "template",
            "required": false,
            "in": "query",
            "description": "Email template (`reset-password`, `invitation`…)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 200,
              "default": 100,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailDeliveryPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/deliveries/push": {
      "get": {
        "operationId": "SystemController_push_v1",
        "parameters": [
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["sent", "failed", "retrying", "skipped"]
            }
          },
          {
            "name": "template",
            "required": false,
            "in": "query",
            "description": "Email template (`reset-password`, `invitation`…)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 200,
              "default": 100,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushDeliveryPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/deliveries/webhooks": {
      "get": {
        "operationId": "SystemController_webhooks_v1",
        "parameters": [
          {
            "name": "hours",
            "required": false,
            "in": "query",
            "description": "Look back (hours)",
            "schema": {
              "minimum": 1,
              "maximum": 720,
              "default": 24,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 200,
              "default": 50,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookFailurePageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/errors": {
      "get": {
        "operationId": "SystemController_errors_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 200,
              "default": 100,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecentErrorPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/system/metrics": {
      "get": {
        "operationId": "SystemController_metrics_v1",
        "parameters": [
          {
            "name": "minutes",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 5,
              "maximum": 60,
              "default": 15,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetricsPanelDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/announcements/active": {
      "get": {
        "operationId": "AnnouncementsController_active_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "query",
            "description": "The organization the agent is working in",
            "schema": {
              "example": "org_0199…",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActiveAnnouncementListDto"
                }
              }
            }
          },
          "404": {
            "description": "Not a member of the organization"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["announcements"]
      }
    },
    "/api/v1/admin/announcements": {
      "get": {
        "operationId": "AdminAnnouncementsController_list_v1",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminAnnouncementListDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "post": {
        "operationId": "AdminAnnouncementsController_create_v1",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAnnouncementDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminAnnouncementDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid window, target or maintenance time"
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/admin/announcements/{announcementId}": {
      "patch": {
        "operationId": "AdminAnnouncementsController_update_v1",
        "parameters": [
          {
            "name": "announcementId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAnnouncementDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminAnnouncementDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown announcement"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      },
      "delete": {
        "operationId": "AdminAnnouncementsController_remove_v1",
        "parameters": [
          {
            "name": "announcementId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Not a platform admin (`code: platform_admin_required`)"
          },
          "404": {
            "description": "Unknown announcement"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "tags": ["admin"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/status": {
      "get": {
        "operationId": "KnowledgeController_status_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeStatusDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Plan gate, embeddings key state and counts",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources": {
      "get": {
        "operationId": "KnowledgeController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/KnowledgeSourceDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/{sourceId}": {
      "get": {
        "operationId": "KnowledgeController_get_v1",
        "parameters": [
          {
            "name": "sourceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "With the article body or FAQ entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["knowledge"]
      },
      "patch": {
        "operationId": "KnowledgeController_update_v1",
        "parameters": [
          {
            "name": "sourceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSourceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Edit a source; content, URL and crawl changes re-index it",
        "tags": ["knowledge"]
      },
      "delete": {
        "operationId": "KnowledgeController_remove_v1",
        "parameters": [
          {
            "name": "sourceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Source, chunks and stored file deleted"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/web": {
      "post": {
        "operationId": "KnowledgeController_createWeb_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebSourceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan has no AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Add a web page (`url`) or a site (`sitemap`)",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/faq": {
      "post": {
        "operationId": "KnowledgeController_createFaq_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFaqSourceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan has no AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/article": {
      "post": {
        "operationId": "KnowledgeController_createArticle_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateArticleSourceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan has no AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/files": {
      "post": {
        "description": "Creates the source (`uploading`) and returns a presigned PUT. Upload the bytes, then call `…/upload-complete`.",
        "operationId": "KnowledgeController_createFile_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFileSourceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeUploadDto"
                }
              }
            }
          },
          "402": {
            "description": "No AI assistant in the plan, or storage full"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Start a file upload (PDF, DOCX, TXT, Markdown; ≤ 20 MB)",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/{sourceId}/upload-complete": {
      "post": {
        "operationId": "KnowledgeController_completeUpload_v1",
        "parameters": [
          {
            "name": "sourceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Confirm a file upload: the stored file is checked, then indexed",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/sources/{sourceId}/sync": {
      "post": {
        "operationId": "KnowledgeController_sync_v1",
        "parameters": [
          {
            "name": "sourceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Re-sync now (unchanged text is not re-embedded)",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/knowledge/search": {
      "post": {
        "description": "Hybrid search (vector + keywords, Reciprocal Rank Fusion). The question is embedded with the organization’s embeddings key; without one, keywords only.",
        "operationId": "KnowledgeController_search_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KnowledgeSearchDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSearchResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "429": {
            "description": "30 searches per minute per organization"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "summary": "Test search: the passages the AI agent would get for a question",
        "tags": ["knowledge"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai": {
      "get": {
        "operationId": "AiController_overview_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Settings, key status (never the keys), models and usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiOverviewDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/settings": {
      "patch": {
        "operationId": "AiController_updateSettings_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAiSettingsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiSettingsDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/keys/chat": {
      "put": {
        "operationId": "AiController_setChatKey_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetChatKeyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored encrypted; test it next",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiKeyStatusDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "delete": {
        "operationId": "AiController_removeChatKey_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removed: the AI stops answering"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/keys/embeddings": {
      "put": {
        "operationId": "AiController_setEmbeddingsKey_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetEmbeddingsKeyDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiKeyStatusDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "delete": {
        "operationId": "AiController_removeEmbeddingsKey_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/test": {
      "post": {
        "operationId": "AiController_test_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lists the key’s models; stores the result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiTestResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/models": {
      "get": {
        "operationId": "AiController_models_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "From the last successful test",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiModelsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/usage": {
      "get": {
        "operationId": "AiController_usage_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiUsageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/agent": {
      "get": {
        "operationId": "AiController_getAgent_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Defaults (id null) until it is first saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiAgentDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "put": {
        "operationId": "AiController_updateAgent_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAiAgentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiAgentDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/playground": {
      "post": {
        "operationId": "AiController_playground_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaygroundRequestDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The answer streams as `ai.playground` events to your agent sockets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiPlaygroundStartedDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/ai/takeover": {
      "post": {
        "operationId": "AiController_takeOver_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The AI stops; the chat is yours if nobody had it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/actions": {
      "get": {
        "operationId": "AiActionsController_listActions_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AiActionDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "post": {
        "operationId": "AiActionsController_createAction_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAiActionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Includes the signing secret, once",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedAiActionDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "An action with this name exists"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/actions/calls": {
      "get": {
        "operationId": "AiActionsController_calls_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Return items older than this id (the previous page’s nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "act_…",
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["succeeded", "failed", "invalid", "rate_limited", "cancelled"]
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The call log, newest first (30 days)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiActionCallPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/actions/{actionId}": {
      "get": {
        "operationId": "AiActionsController_getAction_v1",
        "parameters": [
          {
            "name": "actionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiActionDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "patch": {
        "operationId": "AiActionsController_updateAction_v1",
        "parameters": [
          {
            "name": "actionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAiActionDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiActionDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "delete": {
        "operationId": "AiActionsController_removeAction_v1",
        "parameters": [
          {
            "name": "actionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted; its call log keeps the name"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/actions/{actionId}/rotate-secret": {
      "post": {
        "operationId": "AiActionsController_rotateSecret_v1",
        "parameters": [
          {
            "name": "actionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The new secret, once",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiActionSecretDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/actions/{actionId}/test": {
      "post": {
        "operationId": "AiActionsController_testAction_v1",
        "parameters": [
          {
            "name": "actionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestAiActionDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sends a signed request with `test: true` and returns the response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiActionTestResultDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/reports": {
      "get": {
        "operationId": "AiActionsController_report_v1",
        "parameters": [
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "First day (organization time zone)",
            "schema": {
              "example": "2026-09-01",
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "Last day, inclusive",
            "schema": {
              "example": "2026-09-30",
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Days in the organization’s time zone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiReportsDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/ai-feedback": {
      "get": {
        "operationId": "AiActionsController_listFeedback_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Everyone’s ratings of this chat’s AI replies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AiFeedbackDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/conversations/{conversationId}/messages/{messageId}/ai-feedback": {
      "put": {
        "operationId": "AiActionsController_setFeedback_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetAiFeedbackDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Your rating of an AI reply (replaces it)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiFeedbackDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "delete": {
        "operationId": "AiActionsController_removeFeedback_v1",
        "parameters": [
          {
            "name": "conversationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Your rating removed"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/evals/questions": {
      "get": {
        "operationId": "AiActionsController_listQuestions_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AiEvalQuestionDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "post": {
        "operationId": "AiActionsController_createQuestion_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveAiEvalQuestionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiEvalQuestionDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/evals/questions/{questionId}": {
      "patch": {
        "operationId": "AiActionsController_updateQuestion_v1",
        "parameters": [
          {
            "name": "questionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAiEvalQuestionDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiEvalQuestionDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "delete": {
        "operationId": "AiActionsController_removeQuestion_v1",
        "parameters": [
          {
            "name": "questionId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": ""
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/evals/estimate": {
      "get": {
        "operationId": "AiActionsController_estimate_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show this before starting a run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiEvalEstimateDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/evals/runs": {
      "get": {
        "operationId": "AiActionsController_runs_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The last 20 runs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AiEvalRunDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      },
      "post": {
        "operationId": "AiActionsController_startRun_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartAiEvalRunDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Queued; progress streams as `ai.eval` events to your agent sockets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiEvalRunDetailDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include the AI assistant"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          },
          "409": {
            "description": "No questions, no usable key, cap reached or a run active"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/ai/evals/runs/{runId}": {
      "get": {
        "operationId": "AiActionsController_run_v1",
        "parameters": [
          {
            "name": "runId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiEvalRunDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["ai"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts": {
      "get": {
        "operationId": "ContactsController_list_v1",
        "parameters": [
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Matches name, email, phone or company (contains)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "required": false,
            "in": "query",
            "description": "Only members of this list",
            "schema": {
              "example": "cls_…",
              "type": "string"
            }
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "description": "Only contacts with this tag",
            "schema": {
              "example": "tag_…",
              "type": "string"
            }
          },
          {
            "name": "source",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["widget_form", "set_user", "manual", "import"]
            }
          },
          {
            "name": "hasChats",
            "required": false,
            "in": "query",
            "description": "true: has at least one conversation; false: none",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "lastSeenFrom",
            "required": false,
            "in": "query",
            "description": "Last seen at or after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "lastSeenTo",
            "required": false,
            "in": "query",
            "description": "Last seen before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "sort",
            "required": false,
            "in": "query",
            "schema": {
              "default": "last_seen",
              "type": "string",
              "enum": ["last_seen", "created", "name"]
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Most recently seen first (default sort)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "post": {
        "operationId": "ContactsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/export": {
      "get": {
        "operationId": "ContactsController_export_v1",
        "parameters": [
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Matches name, email, phone or company (contains)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "required": false,
            "in": "query",
            "description": "Only members of this list",
            "schema": {
              "example": "cls_…",
              "type": "string"
            }
          },
          {
            "name": "tagId",
            "required": false,
            "in": "query",
            "description": "Only contacts with this tag",
            "schema": {
              "example": "tag_…",
              "type": "string"
            }
          },
          {
            "name": "source",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["widget_form", "set_user", "manual", "import"]
            }
          },
          {
            "name": "hasChats",
            "required": false,
            "in": "query",
            "description": "true: has at least one conversation; false: none",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "lastSeenFrom",
            "required": false,
            "in": "query",
            "description": "Last seen at or after",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "lastSeenTo",
            "required": false,
            "in": "query",
            "description": "Last seen before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "name": "ids",
            "required": false,
            "in": "query",
            "description": "Comma-separated contact ids (`ctc_…`): export only these (bulk selection)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV (UTF-8 with BOM): id, name, email, phone, company, source, tags, lists, …"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/bulk": {
      "post": {
        "operationId": "ContactsController_bulk_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactBulkDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactBulkResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/{contactId}": {
      "get": {
        "operationId": "ContactsController_get_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "patch": {
        "operationId": "ContactsController_update_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContactDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "delete": {
        "operationId": "ContactsController_remove_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eraseVisitors",
            "required": false,
            "in": "query",
            "description": "Also erase every linked visitor with their chats, messages and files (GDPR erasure; needs org:update)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deletes the contact; its visitors stay unless eraseVisitors=true (GDPR erasure of each, needs org:update)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/{contactId}/merge": {
      "post": {
        "operationId": "ContactsController_merge_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MergeContactDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The merged contact",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/{contactId}/tags": {
      "put": {
        "operationId": "ContactsController_setTags_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetContactTagsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/{contactId}/visitors": {
      "post": {
        "operationId": "ContactsController_linkVisitor_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactVisitorDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Links the visitor (moving it from another contact if it had one)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contacts/{contactId}/visitors/{visitorId}": {
      "delete": {
        "operationId": "ContactsController_unlinkVisitor_v1",
        "parameters": [
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Unlinks the visitor (it stays, anonymous)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/visitors/{visitorId}/contact": {
      "post": {
        "operationId": "ContactsController_forVisitor_v1",
        "parameters": [
          {
            "name": "visitorId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The visitor’s contact: its existing one, else the contact with its email (created if needed), else a new contact from its name and phone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetailDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-lists": {
      "get": {
        "operationId": "ContactListsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ContactListDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "post": {
        "operationId": "ContactListsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactListDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-lists/{listId}": {
      "patch": {
        "operationId": "ContactListsController_update_v1",
        "parameters": [
          {
            "name": "listId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContactListDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "delete": {
        "operationId": "ContactListsController_remove_v1",
        "parameters": [
          {
            "name": "listId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deletes the list; its contacts stay"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-lists/{listId}/members": {
      "post": {
        "operationId": "ContactListsController_addMembers_v1",
        "parameters": [
          {
            "name": "listId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactIdsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`affected`: contacts newly added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactBulkResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-lists/{listId}/members/remove": {
      "post": {
        "operationId": "ContactListsController_removeMembers_v1",
        "parameters": [
          {
            "name": "listId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactIdsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`affected`: contacts removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactBulkResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-imports": {
      "get": {
        "operationId": "ContactImportsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The 20 latest started imports",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ContactImportDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      },
      "post": {
        "operationId": "ContactImportsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactImportDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Creates the import (`uploading`) and returns a presigned PUT for the CSV. Upload it, then call `…/start` with the column mapping.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactImportUploadDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-imports/{importId}/start": {
      "post": {
        "operationId": "ContactImportsController_start_v1",
        "parameters": [
          {
            "name": "importId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartContactImportDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Queued for the worker; poll GET for progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactImportDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/contact-imports/{importId}": {
      "get": {
        "operationId": "ContactImportsController_get_v1",
        "parameters": [
          {
            "name": "importId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactImportDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["contacts"]
      }
    },
    "/api/v1/organizations/{organizationId}/automations": {
      "get": {
        "operationId": "AutomationsController_list_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationListDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      },
      "post": {
        "operationId": "AutomationsController_create_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAutomationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Added after the last rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRuleDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule, unknown ids, or 50 rules already"
          },
          "402": {
            "description": "The plan does not include automations (Business, Pro and Enterprise do)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      }
    },
    "/api/v1/organizations/{organizationId}/automations/runs": {
      "get": {
        "operationId": "AutomationsController_runs_v1",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "type": "number"
            }
          },
          {
            "name": "before",
            "required": false,
            "in": "query",
            "description": "Return items older than this id (the previous page’s nextCursor)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ruleId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "aut_…",
              "type": "string"
            }
          },
          {
            "name": "conversationId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "conv_…",
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": false,
            "in": "query",
            "schema": {
              "example": "vis_…",
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["succeeded", "partial", "failed", "skipped"]
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Newest first, kept 30 days",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRunPageDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      }
    },
    "/api/v1/organizations/{organizationId}/automations/reorder": {
      "post": {
        "operationId": "AutomationsController_reorder_v1",
        "parameters": [
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderAutomationsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationListDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include automations (Business, Pro and Enterprise do)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      }
    },
    "/api/v1/organizations/{organizationId}/automations/{automationId}": {
      "get": {
        "operationId": "AutomationsController_get_v1",
        "parameters": [
          {
            "name": "automationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRuleDto"
                }
              }
            }
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      },
      "patch": {
        "operationId": "AutomationsController_update_v1",
        "parameters": [
          {
            "name": "automationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutomationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRuleDto"
                }
              }
            }
          },
          "402": {
            "description": "The plan does not include automations (Business, Pro and Enterprise do); only `{\"enabled\": false}` works then"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      },
      "delete": {
        "operationId": "AutomationsController_remove_v1",
        "parameters": [
          {
            "name": "automationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "example": "org_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted (its run log keeps the name)"
          },
          "403": {
            "description": "Your role lacks the required permission"
          },
          "404": {
            "description": "Organization not found or you are not a member"
          }
        },
        "security": [
          {
            "bearer": []
          },
          {
            "apiKey": []
          }
        ],
        "tags": ["automations"]
      }
    }
  },
  "info": {
    "title": "ZebChat API",
    "description": "REST API for the ZebChat live chat platform. Authenticate with an agent access token (`bearer`) or, on `/organizations/{organizationId}/…` routes, with an API key (`apiKey`, `Authorization: Bearer zck_…`; needs the API in the plan). A key acts as the member who created it, limited to the key's scopes.",
    "version": "0.1.0",
    "contact": {}
  },
  "tags": [],
  "servers": [],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http",
        "description": "Agent access token from POST /api/v1/auth/login (15 minutes)"
      },
      "apiKey": {
        "scheme": "bearer",
        "bearerFormat": "zck_<prefix>_<secret>",
        "type": "http",
        "description": "API key from POST /api/v1/organizations/{organizationId}/api-keys. Accepted on organization routes whose permission is in the key scopes"
      }
    },
    "schemas": {
      "PublicConfigDto": {
        "type": "object",
        "properties": {
          "cartoKey": {
            "type": "string",
            "nullable": true,
            "description": "CARTO Basemaps key for live maps (public; domain-restricted at CARTO). Null: use the app’s own key or keyless tiles"
          },
          "turnstileSiteKey": {
            "type": "string",
            "nullable": true,
            "description": "Cloudflare Turnstile site key"
          },
          "webPushPublicKey": {
            "type": "string",
            "nullable": true,
            "description": "VAPID public key for web push"
          },
          "supportEmail": {
            "type": "string",
            "nullable": true,
            "format": "email"
          },
          "salesContact": {
            "type": "string",
            "nullable": true,
            "description": "`mailto:` or https URL for \"Contact sales\" (null: no button)"
          },
          "enterpriseText": {
            "type": "string",
            "example": "Custom pricing",
            "description": "Shown instead of a price on custom-priced plans (Enterprise)"
          },
          "signupsEnabled": {
            "type": "boolean",
            "description": "New accounts can register (invitations always work)"
          }
        },
        "required": [
          "cartoKey",
          "turnstileSiteKey",
          "webPushPublicKey",
          "supportEmail",
          "salesContact",
          "enterpriseText",
          "signupsEnabled"
        ]
      },
      "DeviceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "platform": {
            "type": "string",
            "enum": ["android", "ios", "web"]
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "current": {
            "type": "boolean",
            "description": "This login session registered it"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "platform", "userAgent", "current", "lastSeenAt", "createdAt"]
      },
      "WebPushKeysDto": {
        "type": "object",
        "properties": {
          "p256dh": {
            "type": "string"
          },
          "auth": {
            "type": "string"
          }
        },
        "required": ["p256dh", "auth"]
      },
      "WebPushSubscriptionDto": {
        "type": "object",
        "properties": {
          "endpoint": {
            "type": "string",
            "example": "https://fcm.googleapis.com/fcm/send/…"
          },
          "keys": {
            "$ref": "#/components/schemas/WebPushKeysDto"
          },
          "expirationTime": {
            "type": "number",
            "nullable": true
          }
        },
        "required": ["endpoint", "keys"]
      },
      "RegisterDeviceDto": {
        "type": "object",
        "properties": {
          "platform": {
            "type": "string",
            "enum": ["android", "ios", "web"]
          },
          "token": {
            "type": "string",
            "description": "FCM registration token (android, ios)"
          },
          "subscription": {
            "description": "PushSubscription.toJSON() (web)",
            "allOf": [
              {
                "$ref": "#/components/schemas/WebPushSubscriptionDto"
              }
            ]
          }
        },
        "required": ["platform"]
      },
      "PushConfigDto": {
        "type": "object",
        "properties": {
          "webPushPublicKey": {
            "type": "string",
            "nullable": true,
            "description": "VAPID public key for PushManager.subscribe (null: browser push is off)"
          },
          "fcmEnabled": {
            "type": "boolean",
            "description": "Mobile push (FCM) is configured. false: the apps should not register tokens"
          }
        },
        "required": ["webPushPublicKey", "fcmEnabled"]
      },
      "PushSubscriptionChangeDto": {
        "type": "object",
        "properties": {
          "oldEndpoint": {
            "type": "string"
          },
          "oldAuth": {
            "type": "string",
            "description": "keys.auth of the old subscription"
          },
          "subscription": {
            "description": "The new PushSubscription.toJSON()",
            "allOf": [
              {
                "$ref": "#/components/schemas/WebPushSubscriptionDto"
              }
            ]
          }
        },
        "required": ["oldEndpoint", "oldAuth", "subscription"]
      },
      "EventPreferencesDto": {
        "type": "object",
        "properties": {
          "newChat": {
            "type": "boolean"
          },
          "newMessage": {
            "type": "boolean"
          },
          "assigned": {
            "type": "boolean"
          },
          "missedChat": {
            "type": "boolean"
          },
          "offlineMessage": {
            "type": "boolean"
          },
          "newVisitor": {
            "type": "boolean",
            "description": "A visitor arrived (opt-in; email is always false)"
          }
        },
        "required": [
          "newChat",
          "newMessage",
          "assigned",
          "missedChat",
          "offlineMessage",
          "newVisitor"
        ]
      },
      "SoundTonesDto": {
        "type": "object",
        "properties": {
          "newChat": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "newMessage": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "assigned": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "newVisitor": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          }
        },
        "required": ["newChat", "newMessage", "assigned", "newVisitor"]
      },
      "SoundPreferencesDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "volume": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "tones": {
            "$ref": "#/components/schemas/SoundTonesDto"
          },
          "repeatNewChat": {
            "type": "boolean",
            "description": "Ring again until the chat is taken or opened (at most 120 s)"
          },
          "repeatIntervalSeconds": {
            "type": "number",
            "enum": [3, 5, 10, 15, 30]
          }
        },
        "required": ["enabled", "volume", "tones", "repeatNewChat", "repeatIntervalSeconds"]
      },
      "NotificationPreferencesDto": {
        "type": "object",
        "properties": {
          "push": {
            "$ref": "#/components/schemas/EventPreferencesDto"
          },
          "email": {
            "$ref": "#/components/schemas/EventPreferencesDto"
          },
          "sound": {
            "description": "Sounds in the agent app while it is open (not a delivery channel)",
            "allOf": [
              {
                "$ref": "#/components/schemas/SoundPreferencesDto"
              }
            ]
          },
          "previews": {
            "type": "boolean",
            "description": "Show message text and visitor names/emails in push notifications (lock screens). false: title and a generic body only. Email is unaffected.",
            "default": true
          }
        },
        "required": ["push", "email", "sound", "previews"]
      },
      "EventTogglesDto": {
        "type": "object",
        "properties": {
          "newChat": {
            "type": "boolean"
          },
          "newMessage": {
            "type": "boolean"
          },
          "assigned": {
            "type": "boolean"
          },
          "missedChat": {
            "type": "boolean"
          },
          "offlineMessage": {
            "type": "boolean"
          },
          "newVisitor": {
            "type": "boolean",
            "description": "Push only: ignored for email (never emailed)"
          }
        }
      },
      "SoundTonesUpdateDto": {
        "type": "object",
        "properties": {
          "newChat": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "newMessage": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "assigned": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          },
          "newVisitor": {
            "type": "string",
            "enum": [
              "chime",
              "pop",
              "ding",
              "dingDong",
              "bell",
              "knock",
              "ping",
              "harp",
              "soft",
              "alert",
              "none"
            ],
            "description": "`none` = silent"
          }
        }
      },
      "SoundPreferencesUpdateDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Master switch for sounds in the agent app"
          },
          "volume": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "tones": {
            "$ref": "#/components/schemas/SoundTonesUpdateDto"
          },
          "repeatNewChat": {
            "type": "boolean",
            "description": "Ring again for a waiting new chat"
          },
          "repeatIntervalSeconds": {
            "type": "number",
            "enum": [3, 5, 10, 15, 30],
            "description": "Seconds between rings"
          }
        }
      },
      "UpdateNotificationPreferencesDto": {
        "type": "object",
        "properties": {
          "push": {
            "$ref": "#/components/schemas/EventTogglesDto"
          },
          "email": {
            "$ref": "#/components/schemas/EventTogglesDto"
          },
          "sound": {
            "description": "Agent-app sounds",
            "allOf": [
              {
                "$ref": "#/components/schemas/SoundPreferencesUpdateDto"
              }
            ]
          },
          "previews": {
            "type": "boolean",
            "description": "Show message text and visitor names/emails in push notifications (lock screens). false: title and a generic body only. Email is unaffected."
          }
        }
      },
      "ConversationMuteDto": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "until": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["conversationId", "until"]
      },
      "ConversationMuteListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationMuteDto"
            }
          }
        },
        "required": ["data"]
      },
      "SetConversationMuteDto": {
        "type": "object",
        "properties": {
          "muted": {
            "type": "boolean",
            "description": "true mutes for 24 hours (again from now), false unmutes"
          }
        },
        "required": ["muted"]
      },
      "ConversationMuteStateDto": {
        "type": "object",
        "properties": {
          "muted": {
            "type": "boolean"
          },
          "until": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Mute ends"
          }
        },
        "required": ["muted", "until"]
      },
      "AuditActorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "AuditLogDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "aud_…"
          },
          "action": {
            "type": "string",
            "example": "member.role_changed"
          },
          "actor": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AuditActorDto"
              }
            ]
          },
          "targetType": {
            "type": "string",
            "nullable": true,
            "example": "member"
          },
          "targetId": {
            "type": "string",
            "nullable": true,
            "example": "mem_…"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "ip": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "action", "metadata", "createdAt"]
      },
      "AuditLogPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditLogDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "RegisterDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Jane Doe"
          },
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "password": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "example": "correct-horse-battery"
          },
          "organizationName": {
            "type": "string",
            "example": "Acme Inc.",
            "description": "Your first organization (you become its owner)"
          }
        },
        "required": ["name", "email", "password", "organizationName"]
      },
      "AuthTokensDto": {
        "type": "object",
        "properties": {
          "tokenType": {
            "type": "string",
            "example": "Bearer"
          },
          "accessToken": {
            "type": "string",
            "description": "JWT, send as `Authorization: Bearer …`"
          },
          "accessTokenExpiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "refreshToken": {
            "type": "string",
            "description": "Opaque, single use. Exchange at POST /auth/refresh"
          },
          "refreshTokenExpiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "tokenType",
          "accessToken",
          "accessTokenExpiresAt",
          "refreshToken",
          "refreshTokenExpiresAt"
        ]
      },
      "UserDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_01928f5e-7c3a-7b1e-9a4d-3f2e1d0c9b8a"
          },
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "name": {
            "type": "string",
            "example": "Jane Doe"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "Profile photo (an avatar URL)"
          },
          "timeZone": {
            "type": "string",
            "nullable": true,
            "example": "Asia/Kolkata",
            "description": "IANA time zone; null = use the device time zone"
          },
          "emailVerified": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "email", "name", "avatarUrl", "timeZone", "emailVerified", "createdAt"]
      },
      "AuthResponseDto": {
        "type": "object",
        "properties": {
          "tokens": {
            "$ref": "#/components/schemas/AuthTokensDto"
          },
          "user": {
            "$ref": "#/components/schemas/UserDto"
          }
        },
        "required": ["tokens", "user"]
      },
      "MfaChallengeDto": {
        "type": "object",
        "properties": {
          "mfaRequired": {
            "type": "boolean",
            "enum": [true]
          },
          "mfaToken": {
            "type": "string",
            "description": "Send with a code to POST /auth/login/2fa (5 minutes, single use)"
          },
          "methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["totp", "recovery_code"]
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["mfaRequired", "mfaToken", "methods", "expiresAt"]
      },
      "LoginDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "password": {
            "type": "string",
            "example": "correct-horse-battery"
          }
        },
        "required": ["email", "password"]
      },
      "MfaLoginDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "123456",
            "description": "6-digit code from the authenticator app"
          },
          "recoveryCode": {
            "type": "string",
            "example": "ABCDE-FGHIJ",
            "description": "One of the recovery codes (case, spaces and dashes ignored)"
          },
          "mfaToken": {
            "type": "string",
            "description": "From the `mfaRequired` login response (5 minutes, single use)"
          }
        },
        "required": ["mfaToken"]
      },
      "RefreshDto": {
        "type": "object",
        "properties": {
          "refreshToken": {
            "type": "string"
          }
        },
        "required": ["refreshToken"]
      },
      "OrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_01928f5e-…"
          },
          "name": {
            "type": "string",
            "example": "Acme Inc."
          },
          "slug": {
            "type": "string",
            "example": "acme-inc"
          },
          "conversationRetentionDays": {
            "type": "number",
            "enum": [30, 90, 180, 365, 730, 1095, 1825, 2555],
            "nullable": true,
            "description": "Ended conversations (resolved, closed, spam) are deleted this many days after their last activity, with their messages and files; null = keep forever. One of the presets: 30 days, 90 days, 6 months (180), 1 year (365), 2 years (730), 3 years (1095), 5 years (1825) or 7 years (2555). At most the plan's `retentionCapDays`"
          },
          "retentionCapDays": {
            "type": "number",
            "nullable": true,
            "description": "The longest the plan lets this organization keep ended conversations, in days (null = no cap). The sweeper uses the shorter of this and `conversationRetentionDays`; PATCH refuses a longer value with 402 `limit: 'maxRetentionDays'`"
          },
          "timeZone": {
            "type": "string",
            "example": "Europe/Berlin",
            "description": "IANA time zone: default for new websites' business hours"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "suspendedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Set while ZebChat staff have suspended the organization: its routes answer 403 `organization_suspended` (billing still works)"
          },
          "suspendedReason": {
            "type": "string",
            "nullable": true,
            "description": "Why it was suspended"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true,
            "example": "https://api.zebchat.com/api/v1/organizations/org_…/logo?v=…",
            "description": "Public URL of the organization logo (PNG, JPEG or WebP, at most 512 px on its long side, aspect kept); it changes whenever the logo changes, so it can be cached for good. null = no logo (show initials)"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "conversationRetentionDays",
          "retentionCapDays",
          "timeZone",
          "createdAt",
          "suspendedAt",
          "suspendedReason",
          "logoUrl"
        ]
      },
      "MembershipDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "mem_…"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "org:read",
                "org:update",
                "members:read",
                "members:invite",
                "members:manage",
                "websites:read",
                "websites:manage",
                "visitors:read",
                "contacts:read",
                "contacts:manage",
                "conversations:read",
                "conversations:reply",
                "conversations:manage",
                "conversations:supervise",
                "teams:manage",
                "canned:manage",
                "tags:manage",
                "reports:read",
                "billing:manage",
                "audit:read",
                "api:manage",
                "ai:manage",
                "knowledge:read",
                "automations:read",
                "automations:manage"
              ]
            }
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationDto"
          }
        },
        "required": ["id", "role", "permissions", "organization"]
      },
      "ImpersonatorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "name", "email"]
      },
      "ImpersonationInfoDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string",
            "example": "org_…"
          },
          "organizationName": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": ["read", "full"]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Hard end of the session"
          },
          "impersonator": {
            "$ref": "#/components/schemas/ImpersonatorDto"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "organizationId",
          "organizationName",
          "mode",
          "expiresAt",
          "impersonator",
          "reason"
        ]
      },
      "MeResponseDto": {
        "type": "object",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/UserDto"
          },
          "memberships": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MembershipDto"
            }
          },
          "platformAdmin": {
            "type": "boolean",
            "description": "ZebChat staff (PLATFORM_ADMIN_EMAILS, verified email): may use /admin"
          },
          "impersonation": {
            "nullable": true,
            "description": "Set when this session is ZebChat staff logged in as the customer (memberships then list only that organization)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ImpersonationInfoDto"
              }
            ]
          },
          "twoFactorEnabled": {
            "type": "boolean",
            "description": "Two-factor authentication is on for this account"
          }
        },
        "required": ["user", "memberships", "platformAdmin", "impersonation", "twoFactorEnabled"]
      },
      "TokenDto": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Single-use token from the email link"
          }
        },
        "required": ["token"]
      },
      "ForgotPasswordDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "example": "jane@example.com"
          }
        },
        "required": ["email"]
      },
      "ResetPasswordDto": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Single-use token from the email link"
          },
          "password": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "example": "correct-horse-battery"
          }
        },
        "required": ["token", "password"]
      },
      "ChangePasswordDto": {
        "type": "object",
        "properties": {
          "currentPassword": {
            "type": "string"
          },
          "newPassword": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128,
            "example": "correct-horse-battery"
          }
        },
        "required": ["currentPassword", "newPassword"]
      },
      "SessionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ses_…"
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "ip": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "current": {
            "type": "boolean",
            "description": "The session making this request"
          }
        },
        "required": ["id", "userAgent", "ip", "createdAt", "lastUsedAt", "expiresAt", "current"]
      },
      "TwoFactorStatusDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "enabledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "recoveryCodesRemaining": {
            "type": "number",
            "description": "Unused recovery codes (0 while off)"
          }
        },
        "required": ["enabled", "enabledAt", "recoveryCodesRemaining"]
      },
      "TwoFactorPasswordDto": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string",
            "description": "Your current password"
          }
        },
        "required": ["password"]
      },
      "TwoFactorSetupDto": {
        "type": "object",
        "properties": {
          "secret": {
            "type": "string",
            "description": "Base32 secret for manual entry",
            "example": "JBSWY3DPEHPK3PXP…"
          },
          "otpauthUri": {
            "type": "string",
            "description": "Show as a QR code (generate it on the device)"
          },
          "issuer": {
            "type": "string",
            "example": "ZebChat"
          },
          "accountName": {
            "type": "string",
            "example": "jane@example.com"
          },
          "algorithm": {
            "type": "string",
            "enum": ["SHA1"]
          },
          "digits": {
            "type": "number",
            "example": 6
          },
          "period": {
            "type": "number",
            "example": 30
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Confirm a code before this"
          }
        },
        "required": [
          "secret",
          "otpauthUri",
          "issuer",
          "accountName",
          "algorithm",
          "digits",
          "period",
          "expiresAt"
        ]
      },
      "TwoFactorCodeDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "123456",
            "description": "6-digit code from the authenticator app"
          }
        },
        "required": ["code"]
      },
      "RecoveryCodesDto": {
        "type": "object",
        "properties": {
          "recoveryCodes": {
            "example": ["ABCDE-FGHIJ"],
            "description": "10 single-use codes, shown only this once",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["recoveryCodes"]
      },
      "DisableTwoFactorDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "123456",
            "description": "6-digit code from the authenticator app"
          },
          "recoveryCode": {
            "type": "string",
            "example": "ABCDE-FGHIJ",
            "description": "One of the recovery codes (case, spaces and dashes ignored)"
          },
          "password": {
            "type": "string",
            "description": "Your current password"
          }
        },
        "required": ["password"]
      },
      "UpdateProfileDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Jane Doe",
            "minLength": 1,
            "maxLength": 100
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "A preset from GET /avatars/presets or your own upload (POST /avatars); null removes it"
          },
          "timeZone": {
            "type": "string",
            "nullable": true,
            "example": "Asia/Kolkata",
            "description": "IANA time zone (GET /timezones); null = use the device time zone"
          }
        }
      },
      "CreateOrganizationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Acme Inc.",
            "minLength": 2,
            "maxLength": 80
          }
        },
        "required": ["name"]
      },
      "UpdateOrganizationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Acme Inc.",
            "minLength": 2,
            "maxLength": 80
          },
          "conversationRetentionDays": {
            "type": "number",
            "enum": [30, 90, 180, 365, 730, 1095, 1825, 2555],
            "nullable": true,
            "description": "Ended conversations (resolved, closed, spam) are deleted this many days after their last activity, with their messages and files; null = keep forever. One of the presets: 30 days, 90 days, 6 months (180), 1 year (365), 2 years (730), 3 years (1095), 5 years (1825) or 7 years (2555). At most the plan's `retentionCapDays`"
          },
          "timeZone": {
            "type": "string",
            "example": "Europe/Berlin",
            "description": "IANA time zone (GET /timezones): default for new websites' business hours"
          }
        }
      },
      "MemberUserDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["id", "name", "email", "avatarUrl"]
      },
      "MemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "mem_…"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "user": {
            "$ref": "#/components/schemas/MemberUserDto"
          },
          "maxChats": {
            "type": "number",
            "nullable": true,
            "description": "Max concurrent chats; null = unlimited"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "role", "user", "maxChats", "joinedAt"]
      },
      "UpdateMemberDto": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "maxChats": {
            "type": "number",
            "nullable": true,
            "minimum": 0,
            "maximum": 100,
            "description": "Max concurrent auto-assigned chats; null = unlimited, 0 = never auto-assign"
          }
        }
      },
      "CreateInvitationDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "example": "agent@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"],
            "example": "agent"
          }
        },
        "required": ["email", "role"]
      },
      "InviterDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "InvitationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "inv_…"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "status": {
            "type": "string",
            "enum": ["pending", "accepted", "revoked", "expired"]
          },
          "invitedBy": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/InviterDto"
              }
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "email", "role", "status", "expiresAt", "createdAt"]
      },
      "InvitationPreviewDto": {
        "type": "object",
        "properties": {
          "organizationName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "status": {
            "type": "string",
            "enum": ["pending", "accepted", "revoked", "expired"]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["organizationName", "email", "role", "status", "expiresAt"]
      },
      "AcceptInvitationDto": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Token from the invitation email link"
          }
        },
        "required": ["token"]
      },
      "TeamMemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "name", "email"]
      },
      "TeamDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "team_…"
          },
          "name": {
            "type": "string",
            "example": "Support"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamMemberDto"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "description", "members", "createdAt"]
      },
      "CreateTeamDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Support"
          },
          "description": {
            "type": "string",
            "maxLength": 300
          }
        },
        "required": ["name"]
      },
      "UpdateTeamDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "SetTeamMembersDto": {
        "type": "object",
        "properties": {
          "userIds": {
            "example": ["usr_…"],
            "description": "Replaces the team’s members",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["userIds"]
      },
      "AgentTeamDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "team_…"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "SkillRefDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "skl_…"
          },
          "name": {
            "type": "string",
            "example": "Billing"
          }
        },
        "required": ["id", "name"]
      },
      "AgentDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "memberId": {
            "type": "string",
            "example": "mem_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "status": {
            "type": "string",
            "enum": ["online", "away", "busy", "offline"]
          },
          "activeChats": {
            "type": "number",
            "description": "Assigned active conversations"
          },
          "maxChats": {
            "type": "number",
            "nullable": true,
            "description": "null = unlimited"
          },
          "teams": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentTeamDto"
            }
          },
          "skills": {
            "description": "Skills for skills routing",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillRefDto"
            }
          }
        },
        "required": [
          "userId",
          "memberId",
          "name",
          "email",
          "avatarUrl",
          "role",
          "status",
          "activeChats",
          "maxChats",
          "teams",
          "skills"
        ]
      },
      "SetStatusDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["online", "away", "busy"]
          }
        },
        "required": ["status"]
      },
      "RoutingSettingsDto": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["auto", "manual"]
          },
          "strategy": {
            "type": "string",
            "enum": ["least_active", "round_robin"]
          },
          "skillRouting": {
            "type": "string",
            "enum": ["off", "prefer", "require"],
            "description": "How a chat's required skill is used: `off` ignores it; `prefer` tries agents with the skill first and falls back to anyone; `require` waits for an agent with the skill"
          }
        },
        "required": ["mode", "strategy", "skillRouting"]
      },
      "QueuedChatDto": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "position": {
            "type": "number",
            "example": 2,
            "description": "The visitor's place in line (1 = next)"
          }
        },
        "required": ["conversationId", "position"]
      },
      "QueueSummaryDto": {
        "type": "object",
        "properties": {
          "activeChats": {
            "type": "number",
            "description": "Live chats people are answering now (active and assigned; AI-owned chats and offline-form messages excluded)"
          },
          "limit": {
            "type": "number",
            "nullable": true,
            "description": "The plan's concurrent-chat limit (null = unlimited)"
          },
          "atLimit": {
            "type": "boolean",
            "description": "At the limit: waiting chats are assigned only as chats end"
          },
          "waiting": {
            "type": "number",
            "description": "Live chats waiting for a person"
          },
          "queue": {
            "description": "Waiting chats, oldest first (at most 200)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueuedChatDto"
            }
          }
        },
        "required": ["activeChats", "limit", "atLimit", "waiting", "queue"]
      },
      "UpdateRoutingSettingsDto": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["auto", "manual"]
          },
          "strategy": {
            "type": "string",
            "enum": ["least_active", "round_robin"]
          },
          "skillRouting": {
            "type": "string",
            "enum": ["off", "prefer", "require"],
            "description": "How a chat's required skill is used: `off` ignores it; `prefer` tries agents with the skill first and falls back to anyone; `require` waits for an agent with the skill"
          }
        }
      },
      "SkillMemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "SkillDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "skl_…"
          },
          "name": {
            "type": "string",
            "example": "Billing"
          },
          "members": {
            "description": "Members who have the skill",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillMemberDto"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "members", "createdAt"]
      },
      "SaveSkillDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Billing",
            "maxLength": 40
          }
        },
        "required": ["name"]
      },
      "SetMemberSkillsDto": {
        "type": "object",
        "properties": {
          "skillIds": {
            "example": ["skl_…"],
            "description": "Replaces the member's skills",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["skillIds"]
      },
      "MemberSkillsDto": {
        "type": "object",
        "properties": {
          "memberId": {
            "type": "string",
            "example": "mem_…"
          },
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillRefDto"
            }
          }
        },
        "required": ["memberId", "userId", "skills"]
      },
      "AccountDeletionBlockingOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "otherMembers": {
            "type": "number",
            "description": "Members besides you"
          }
        },
        "required": ["id", "name", "slug", "otherMembers"]
      },
      "AccountDeletionOwnedOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "activeSubscription": {
            "type": "boolean",
            "description": "A Stripe or PayPal subscription can still charge it: cancel it (Billing) before deleting"
          }
        },
        "required": ["id", "name", "slug", "activeSubscription"]
      },
      "AccountDeletionMembershipDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "example": "agent",
            "description": "Your role there"
          }
        },
        "required": ["id", "name", "slug", "role"]
      },
      "AccountDeletionPreviewDto": {
        "type": "object",
        "properties": {
          "canDelete": {
            "type": "boolean",
            "description": "False while blockingOrganizations is not empty or an owned organization has an active subscription"
          },
          "twoFactorEnabled": {
            "type": "boolean",
            "description": "The request then needs `code` or `recoveryCode`"
          },
          "blockingOrganizations": {
            "description": "You are the only owner and there are other members: make another member an owner, or remove the members, first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionBlockingOrganizationDto"
            }
          },
          "ownedOrganizations": {
            "description": "You are the only member: deleted with your account (send `deleteOwnedOrganizations: true`)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionOwnedOrganizationDto"
            }
          },
          "memberships": {
            "description": "Organizations you leave (their data stays with them)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionMembershipDto"
            }
          }
        },
        "required": [
          "canDelete",
          "twoFactorEnabled",
          "blockingOrganizations",
          "ownedOrganizations",
          "memberships"
        ]
      },
      "DeleteAccountDto": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string",
            "description": "Your current password"
          },
          "code": {
            "type": "string",
            "example": "123456",
            "description": "Code from your authenticator app (when your account has 2FA on)"
          },
          "recoveryCode": {
            "type": "string",
            "example": "ABCDE-FGHIJ",
            "description": "Or one of your recovery codes instead of `code`"
          },
          "deleteOwnedOrganizations": {
            "type": "boolean",
            "description": "Required (true) when you are the only member of organizations: they are deleted with all their data"
          }
        },
        "required": ["password"]
      },
      "AccountDeletionOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        },
        "required": ["id", "name", "slug"]
      },
      "DeletedAccountDto": {
        "type": "object",
        "properties": {
          "deletedOrganizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionOrganizationDto"
            }
          },
          "leftOrganizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionOrganizationDto"
            }
          }
        },
        "required": ["deletedOrganizations", "leftOrganizations"]
      },
      "AccountDeletionConflictDto": {
        "type": "object",
        "properties": {
          "statusCode": {
            "type": "number",
            "example": 409
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": ["sole_owner", "owned_organizations", "active_subscription"]
          },
          "organizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountDeletionOrganizationDto"
            }
          }
        },
        "required": ["statusCode", "message", "code", "organizations"]
      },
      "StepUpDto": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string",
            "description": "The admin's own account password"
          },
          "code": {
            "type": "string",
            "example": "123456",
            "description": "Code from your authenticator app (required when your account has 2FA on)"
          }
        },
        "required": ["password"]
      },
      "StepUpResponseDto": {
        "type": "object",
        "properties": {
          "stepUpToken": {
            "type": "string",
            "description": "Send as the X-Step-Up header on dangerous admin requests (10 minutes, this session only)"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["stepUpToken", "expiresAt"]
      },
      "PlatformAuditActorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "example": "usr_…"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "email"]
      },
      "PlatformAuditTargetDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["organization", "user", "session", "setting", "plan", "system"]
          },
          "id": {
            "type": "string",
            "nullable": true,
            "example": "org_…"
          },
          "label": {
            "type": "string",
            "nullable": true,
            "description": "Name or email when it happened"
          }
        },
        "required": ["type", "id", "label"]
      },
      "PlatformAuditLogDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "pal_…"
          },
          "action": {
            "type": "string",
            "enum": [
              "step_up.verified",
              "step_up.failed",
              "organization.plan_set",
              "organization.plan_canceled",
              "organization.suspended",
              "organization.unsuspended",
              "organization.deleted",
              "user.email_verified",
              "user.signed_out",
              "user.disabled",
              "user.enabled",
              "user.password_reset_sent",
              "user.two_factor_reset",
              "user.account_deleted",
              "impersonation.started",
              "impersonation.ended",
              "queue.job_retried",
              "queue.failed_retried",
              "queue.job_removed",
              "queue.paused",
              "queue.resumed",
              "queue.dead_letter_requeued",
              "announcement.created",
              "announcement.updated",
              "announcement.deleted",
              "settings.updated",
              "settings.test_email_sent",
              "settings.secrets_resealed",
              "plan.updated",
              "plan.deleted",
              "organization.limits_set",
              "organization.limits_cleared",
              "organization.price_set",
              "organization.price_cleared"
            ]
          },
          "actor": {
            "$ref": "#/components/schemas/PlatformAuditActorDto"
          },
          "target": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/PlatformAuditTargetDto"
              }
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "ip": {
            "type": "string",
            "nullable": true
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "action", "actor", "target", "metadata", "ip", "userAgent", "createdAt"]
      },
      "PlatformAuditLogPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlatformAuditLogDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data", "nextCursor"]
      },
      "AdminOwnerDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "name", "email"]
      },
      "AdminSubscriptionDto": {
        "type": "object",
        "properties": {
          "planCode": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"]
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "status": {
            "type": "string",
            "enum": ["trialing", "active", "past_due", "canceled", "incomplete"]
          },
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal", "manual"]
          },
          "currentPeriodEnd": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "graceUntil": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "note": {
            "type": "string",
            "nullable": true,
            "description": "Manual plans: why"
          }
        },
        "required": [
          "planCode",
          "interval",
          "status",
          "provider",
          "currentPeriodEnd",
          "cancelAtPeriodEnd",
          "graceUntil",
          "note"
        ]
      },
      "AdminUsageDto": {
        "type": "object",
        "properties": {
          "members": {
            "type": "number"
          },
          "websites": {
            "type": "number"
          },
          "conversationsThisMonth": {
            "type": "number"
          },
          "storageBytes": {
            "type": "number"
          }
        },
        "required": ["members", "websites", "conversationsThisMonth", "storageBytes"]
      },
      "AdminOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true,
            "description": "Public logo URL (null = none)"
          },
          "timeZone": {
            "type": "string",
            "example": "Europe/Berlin"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "owner": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AdminOwnerDto"
              }
            ]
          },
          "plan": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"],
            "description": "The plan in force right now"
          },
          "subscription": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AdminSubscriptionDto"
              }
            ]
          },
          "usage": {
            "$ref": "#/components/schemas/AdminUsageDto"
          },
          "suspendedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "suspendedReason": {
            "type": "string",
            "nullable": true
          },
          "isTest": {
            "type": "boolean",
            "description": "Owner on a test domain (hidden unless includeTest)"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "logoUrl",
          "timeZone",
          "createdAt",
          "owner",
          "plan",
          "subscription",
          "usage",
          "suspendedAt",
          "suspendedReason",
          "isTest"
        ]
      },
      "AdminOrganizationListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminOrganizationDto"
            }
          },
          "total": {
            "type": "number",
            "description": "Matching organizations across all pages"
          },
          "limit": {
            "type": "number"
          },
          "offset": {
            "type": "number"
          }
        },
        "required": ["data", "total", "limit", "offset"]
      },
      "SetManualPlanDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["starter", "business", "pro", "enterprise"]
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "periodEnd": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "When the plan ends (must be in the future); null for no end"
          },
          "note": {
            "type": "string",
            "maxLength": 500,
            "example": "Partner deal, ticket #123"
          }
        },
        "required": ["plan", "interval", "periodEnd", "note"]
      },
      "OverviewProviderSplitDto": {
        "type": "object",
        "properties": {
          "stripe": {
            "type": "number"
          },
          "paypal": {
            "type": "number"
          }
        },
        "required": ["stripe", "paypal"]
      },
      "OverviewSubscriptionCountsDto": {
        "type": "object",
        "properties": {
          "stripe": {
            "type": "number"
          },
          "paypal": {
            "type": "number"
          },
          "manual": {
            "type": "number"
          }
        },
        "required": ["stripe", "paypal", "manual"]
      },
      "OverviewPlanRevenueDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"]
          },
          "mrrCents": {
            "type": "number"
          },
          "subscriptions": {
            "type": "number"
          }
        },
        "required": ["plan", "mrrCents", "subscriptions"]
      },
      "OverviewRevenueDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "enum": ["usd"]
          },
          "mrrCents": {
            "type": "number",
            "description": "Paying Stripe + PayPal subscriptions, per month, cents"
          },
          "arrCents": {
            "type": "number"
          },
          "byProvider": {
            "$ref": "#/components/schemas/OverviewProviderSplitDto"
          },
          "manualMrrCents": {
            "type": "number",
            "description": "Manual (comped/invoiced) plans at list price, per month"
          },
          "subscriptions": {
            "$ref": "#/components/schemas/OverviewSubscriptionCountsDto"
          },
          "byPlan": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OverviewPlanRevenueDto"
            }
          }
        },
        "required": [
          "currency",
          "mrrCents",
          "arrCents",
          "byProvider",
          "manualMrrCents",
          "subscriptions",
          "byPlan"
        ]
      },
      "OverviewSignupDto": {
        "type": "object",
        "properties": {
          "day": {
            "type": "string",
            "example": "2026-10-05"
          },
          "count": {
            "type": "number"
          }
        },
        "required": ["day", "count"]
      },
      "OverviewCustomersDto": {
        "type": "object",
        "properties": {
          "organizations": {
            "type": "number"
          },
          "paying": {
            "type": "number"
          },
          "manual": {
            "type": "number"
          },
          "free": {
            "type": "number"
          },
          "trialing": {
            "type": "number"
          },
          "suspended": {
            "type": "number"
          },
          "newThisMonth": {
            "type": "number"
          },
          "churnedThisMonth": {
            "type": "number"
          },
          "testOrganizations": {
            "type": "number"
          },
          "users": {
            "type": "number"
          },
          "signups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OverviewSignupDto"
            }
          }
        },
        "required": [
          "organizations",
          "paying",
          "manual",
          "free",
          "trialing",
          "suspended",
          "newThisMonth",
          "churnedThisMonth",
          "testOrganizations",
          "users",
          "signups"
        ]
      },
      "OverviewActivityDto": {
        "type": "object",
        "properties": {
          "openChats": {
            "type": "number"
          },
          "activeChats": {
            "type": "number"
          },
          "messagesToday": {
            "type": "number"
          },
          "visitorsOnline": {
            "type": "number"
          },
          "agentsOnline": {
            "type": "number"
          },
          "failedPayments": {
            "type": "number"
          }
        },
        "required": [
          "openChats",
          "activeChats",
          "messagesToday",
          "visitorsOnline",
          "agentsOnline",
          "failedPayments"
        ]
      },
      "AdminOverviewDto": {
        "type": "object",
        "properties": {
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "includeTest": {
            "type": "boolean"
          },
          "revenue": {
            "$ref": "#/components/schemas/OverviewRevenueDto"
          },
          "customers": {
            "$ref": "#/components/schemas/OverviewCustomersDto"
          },
          "activity": {
            "$ref": "#/components/schemas/OverviewActivityDto"
          }
        },
        "required": ["generatedAt", "includeTest", "revenue", "customers", "activity"]
      },
      "AdminMemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "mem_…"
          },
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "emailVerified": {
            "type": "boolean"
          },
          "lastLoginAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "disabledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "userId",
          "name",
          "email",
          "role",
          "emailVerified",
          "lastLoginAt",
          "disabledAt",
          "joinedAt"
        ]
      },
      "AdminWebsiteDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "domain", "createdAt"]
      },
      "SubscriptionSummaryDto": {
        "type": "object",
        "properties": {
          "planCode": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"]
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "status": {
            "type": "string",
            "enum": ["trialing", "active", "past_due", "canceled", "incomplete"]
          },
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal", "manual"],
            "description": "`manual`: set by ZebChat (comped or invoiced); change it through support"
          },
          "defaultPlan": {
            "type": "boolean",
            "description": "The default plan new organizations get (provider `manual`); checkout can replace it"
          },
          "currentPeriodEnd": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "graceUntil": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "After a failed payment the plan keeps working until then"
          }
        },
        "required": [
          "planCode",
          "interval",
          "status",
          "provider",
          "defaultPlan",
          "currentPeriodEnd",
          "cancelAtPeriodEnd",
          "graceUntil"
        ]
      },
      "UsageDto": {
        "type": "object",
        "properties": {
          "agents": {
            "type": "number",
            "description": "Seats: members who answer chats + open invitations for such roles"
          },
          "websites": {
            "type": "number"
          },
          "concurrentChats": {
            "type": "number",
            "description": "Live chats people are answering now (compare with limits.concurrentChats; more visitors wait in the queue)"
          },
          "conversationsThisMonth": {
            "type": "number",
            "description": "New conversations this month (information; no plan limits it)"
          },
          "messagesThisMonth": {
            "type": "number"
          },
          "apiRequestsThisMonth": {
            "type": "number",
            "description": "Requests made with API keys"
          },
          "storageBytes": {
            "type": "number"
          }
        },
        "required": [
          "agents",
          "websites",
          "concurrentChats",
          "conversationsThisMonth",
          "messagesThisMonth",
          "apiRequestsThisMonth",
          "storageBytes"
        ]
      },
      "CustomPriceOfferDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["enterprise"]
          },
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal"]
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "amountCents": {
            "type": "number",
            "description": "Per interval, in cents of `currency`"
          },
          "currency": {
            "type": "string",
            "example": "usd"
          },
          "available": {
            "type": "boolean",
            "description": "The provider is set up on this server (checkout works)"
          }
        },
        "required": ["plan", "provider", "interval", "amountCents", "currency", "available"]
      },
      "BillingOverviewDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"],
            "description": "The plan in effect now (Free without a subscription)"
          },
          "limits": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "nullable": true
            }
          },
          "customLimits": {
            "type": "boolean",
            "description": "The limits are the organization’s own (set by ZebChat, e.g. Enterprise), not the plan’s"
          },
          "features": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "subscription": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SubscriptionSummaryDto"
              }
            ]
          },
          "usage": {
            "$ref": "#/components/schemas/UsageDto"
          },
          "providers": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["stripe", "paypal"]
            }
          },
          "customPrice": {
            "nullable": true,
            "description": "Enterprise: the price ZebChat set up for this organization (checkout with `plan: enterprise`, this provider and interval)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomPriceOfferDto"
              }
            ]
          }
        },
        "required": [
          "plan",
          "limits",
          "customLimits",
          "features",
          "subscription",
          "usage",
          "providers",
          "customPrice"
        ]
      },
      "InvoiceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "number": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": ["paid", "open", "void", "uncollectible"]
          },
          "amountCents": {
            "type": "number"
          },
          "currency": {
            "type": "string",
            "example": "usd"
          },
          "periodStart": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "periodEnd": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "hostedUrl": {
            "type": "string",
            "nullable": true
          },
          "pdfUrl": {
            "type": "string",
            "nullable": true
          },
          "issuedAt": {
            "type": "string",
            "format": "date-time"
          },
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal"]
          }
        },
        "required": [
          "id",
          "number",
          "status",
          "amountCents",
          "currency",
          "periodStart",
          "periodEnd",
          "hostedUrl",
          "pdfUrl",
          "issuedAt",
          "provider"
        ]
      },
      "ImpersonationOrgDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "ImpersonationStaffDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "name", "email"]
      },
      "ImpersonationOwnerDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "email"]
      },
      "AdminImpersonationSessionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ses_…"
          },
          "organization": {
            "$ref": "#/components/schemas/ImpersonationOrgDto"
          },
          "impersonator": {
            "$ref": "#/components/schemas/ImpersonationStaffDto"
          },
          "actingAs": {
            "description": "The owner the session acts as",
            "allOf": [
              {
                "$ref": "#/components/schemas/ImpersonationOwnerDto"
              }
            ]
          },
          "mode": {
            "type": "string",
            "enum": ["read", "full"]
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "The hard end"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time"
          },
          "ip": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "organization",
          "impersonator",
          "actingAs",
          "mode",
          "reason",
          "startedAt",
          "expiresAt",
          "lastUsedAt",
          "ip"
        ]
      },
      "OrganizationCustomPriceDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal"]
          },
          "priceId": {
            "type": "string",
            "example": "price_1Q…",
            "description": "Stripe price id or PayPal plan id"
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "amountCents": {
            "type": "number",
            "description": "Per interval, in cents (what the dashboard shows)"
          },
          "currency": {
            "type": "string",
            "example": "usd"
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "provider",
          "priceId",
          "interval",
          "amountCents",
          "currency",
          "note",
          "updatedAt"
        ]
      },
      "AdminOrganizationDetailDto": {
        "type": "object",
        "properties": {
          "organization": {
            "$ref": "#/components/schemas/AdminOrganizationDto"
          },
          "retentionDays": {
            "type": "number",
            "nullable": true,
            "description": "Conversation retention, days"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminMemberDto"
            }
          },
          "websites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminWebsiteDto"
            }
          },
          "billing": {
            "description": "Plan, limits and usage, as the owner sees it",
            "allOf": [
              {
                "$ref": "#/components/schemas/BillingOverviewDto"
              }
            ]
          },
          "invoices": {
            "description": "Latest 20",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvoiceDto"
            }
          },
          "auditLog": {
            "description": "The organization's audit log, latest 25",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditLogDto"
            }
          },
          "activeImpersonations": {
            "type": "number",
            "description": "Live staff impersonation sessions in this organization"
          },
          "impersonations": {
            "description": "Those sessions: who, mode, started, expires (end one with step-up)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminImpersonationSessionDto"
            }
          },
          "customPrice": {
            "nullable": true,
            "description": "Enterprise: the organization's own Stripe price or PayPal plan",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/OrganizationCustomPriceDto"
              }
            ]
          }
        },
        "required": [
          "organization",
          "retentionDays",
          "members",
          "websites",
          "billing",
          "invoices",
          "auditLog",
          "activeImpersonations",
          "impersonations",
          "customPrice"
        ]
      },
      "SuspendOrganizationDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500,
            "example": "Chargeback fraud, ticket #88"
          },
          "notifyOwner": {
            "type": "boolean",
            "default": true,
            "description": "Email the organization's owners (reason, what it means, support contact)"
          }
        },
        "required": ["reason"]
      },
      "UnsuspendOrganizationDto": {
        "type": "object",
        "properties": {
          "notifyOwner": {
            "type": "boolean",
            "default": true,
            "description": "Email the organization's owners"
          }
        }
      },
      "OrganizationPriceResponseDto": {
        "type": "object",
        "properties": {
          "customPrice": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/OrganizationCustomPriceDto"
              }
            ]
          }
        },
        "required": ["customPrice"]
      },
      "SetOrganizationPriceDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal"]
          },
          "priceId": {
            "type": "string",
            "maxLength": 100,
            "example": "price_1QxEnterpriseAcme",
            "description": "Stripe: a recurring price id (`price_…`). PayPal: a plan id (`P-…`)"
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"],
            "description": "The interval the price bills"
          },
          "amountCents": {
            "type": "number",
            "minimum": 1,
            "description": "Per interval, in cents (shown to the owner)"
          },
          "currency": {
            "type": "string",
            "default": "usd",
            "example": "usd"
          },
          "note": {
            "type": "string",
            "maxLength": 500,
            "example": "Contract #42, 25 seats"
          }
        },
        "required": ["provider", "priceId", "interval", "amountCents", "note"]
      },
      "DeleteOrganizationDto": {
        "type": "object",
        "properties": {
          "confirmSlug": {
            "type": "string",
            "description": "The organization's slug, typed by the admin to confirm"
          }
        },
        "required": ["confirmSlug"]
      },
      "DeletedOrganizationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "org_…"
          },
          "name": {
            "type": "string"
          },
          "filesRemoved": {
            "type": "number",
            "description": "Storage objects removed (files and thumbnails)"
          }
        },
        "required": ["id", "name", "filesRemoved"]
      },
      "AdminUserDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          },
          "emailVerified": {
            "type": "boolean"
          },
          "lastLoginAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "disabledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "disabledReason": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "isTest": {
            "type": "boolean"
          },
          "organizations": {
            "type": "number"
          },
          "ownedOrganizations": {
            "type": "number"
          },
          "activeSessions": {
            "type": "number"
          },
          "platformAdmin": {
            "type": "boolean",
            "description": "On PLATFORM_ADMIN_EMAILS"
          },
          "twoFactorEnabled": {
            "type": "boolean",
            "description": "Two-factor authentication (TOTP) is on"
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "avatarUrl",
          "emailVerified",
          "lastLoginAt",
          "disabledAt",
          "disabledReason",
          "createdAt",
          "isTest",
          "organizations",
          "ownedOrganizations",
          "activeSessions",
          "platformAdmin",
          "twoFactorEnabled"
        ]
      },
      "AdminUserListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUserDto"
            }
          },
          "total": {
            "type": "number"
          },
          "limit": {
            "type": "number"
          },
          "offset": {
            "type": "number"
          }
        },
        "required": ["data", "total", "limit", "offset"]
      },
      "AdminUserMembershipDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string",
            "example": "org_…"
          },
          "organizationName": {
            "type": "string"
          },
          "organizationSlug": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "supervisor", "agent", "viewer"]
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          },
          "suspendedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "organizationId",
          "organizationName",
          "organizationSlug",
          "role",
          "joinedAt",
          "suspendedAt"
        ]
      },
      "AdminUserSessionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ses_…"
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "ip": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "impersonatorUserId": {
            "type": "string",
            "nullable": true,
            "example": "usr_…",
            "description": "Set for staff impersonation sessions: who is acting as this user"
          }
        },
        "required": [
          "id",
          "userAgent",
          "ip",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "impersonatorUserId"
        ]
      },
      "AdminUserDeviceDto": {
        "type": "object",
        "properties": {
          "platform": {
            "type": "string",
            "enum": ["android", "ios", "web"]
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["platform", "userAgent", "lastSeenAt", "createdAt"]
      },
      "AdminUserDetailDto": {
        "type": "object",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/AdminUserDto"
          },
          "timeZone": {
            "type": "string",
            "nullable": true,
            "description": "Their own IANA zone"
          },
          "memberships": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUserMembershipDto"
            }
          },
          "sessions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUserSessionDto"
            }
          },
          "devices": {
            "description": "Push devices",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUserDeviceDto"
            }
          }
        },
        "required": ["user", "timeZone", "memberships", "sessions", "devices"]
      },
      "SignedOutDto": {
        "type": "object",
        "properties": {
          "sessionsRevoked": {
            "type": "number",
            "description": "Sessions that were ended"
          }
        },
        "required": ["sessionsRevoked"]
      },
      "DisableUserDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500,
            "example": "Spam account"
          }
        },
        "required": ["reason"]
      },
      "StartImpersonationDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string",
            "example": "org_…"
          },
          "mode": {
            "type": "string",
            "enum": ["read", "full"],
            "description": "`read` blocks every change"
          },
          "reason": {
            "type": "string",
            "maxLength": 500,
            "example": "Ticket #123: widget not showing"
          }
        },
        "required": ["organizationId", "mode", "reason"]
      },
      "ImpersonationTokensDto": {
        "type": "object",
        "properties": {
          "tokenType": {
            "type": "string",
            "example": "Bearer"
          },
          "accessToken": {
            "type": "string"
          },
          "accessTokenExpiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "refreshToken": {
            "type": "string"
          },
          "refreshTokenExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "The hard end (at most 30 minutes)"
          }
        },
        "required": [
          "tokenType",
          "accessToken",
          "accessTokenExpiresAt",
          "refreshToken",
          "refreshTokenExpiresAt"
        ]
      },
      "StartImpersonationResponseDto": {
        "type": "object",
        "properties": {
          "tokens": {
            "$ref": "#/components/schemas/ImpersonationTokensDto"
          },
          "impersonation": {
            "$ref": "#/components/schemas/ImpersonationInfoDto"
          }
        },
        "required": ["tokens", "impersonation"]
      },
      "PlanCatalogDto": {
        "type": "object",
        "properties": {
          "plans": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "PlanDefinition[] (packages/types/src/billing.ts), active and visible plans in order (Admin → Plans): prices in cents of `currency`, `customPricing` (no list price: contact sales), limits (null = unlimited), features"
          },
          "providers": {
            "type": "array",
            "description": "Providers set up on this server",
            "items": {
              "type": "string",
              "enum": ["stripe", "paypal"]
            }
          },
          "customPricingText": {
            "type": "string",
            "example": "Custom pricing",
            "description": "Shown instead of a price on plans with `customPricing` (Enterprise)"
          },
          "salesContact": {
            "type": "string",
            "nullable": true,
            "description": "`mailto:` or https URL for \"Contact sales\" (null: show no button)"
          }
        },
        "required": ["plans", "providers", "customPricingText", "salesContact"]
      },
      "CheckoutDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["starter", "business", "pro", "enterprise"]
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          },
          "provider": {
            "type": "string",
            "enum": ["stripe", "paypal"]
          }
        },
        "required": ["plan", "interval", "provider"]
      },
      "RedirectDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "nullable": true,
            "description": "Send the user here (null: nothing to do)"
          }
        },
        "required": ["url"]
      },
      "ChangePlanDto": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"],
            "description": "`free` cancels at the end of the paid period"
          },
          "interval": {
            "type": "string",
            "enum": ["month", "year"]
          }
        },
        "required": ["plan", "interval"]
      },
      "CancelDto": {
        "type": "object",
        "properties": {
          "atPeriodEnd": {
            "type": "boolean",
            "default": true,
            "description": "Keep the plan until the paid period ends"
          }
        }
      },
      "LauncherDto": {
        "type": "object",
        "properties": {
          "style": {
            "type": "string",
            "enum": ["bubble", "label", "tab"]
          },
          "label": {
            "type": "string",
            "maxLength": 40,
            "example": "Chat with us",
            "description": "Text for the `label` launcher and the side `tab`; send \"\" to remove it"
          }
        }
      },
      "FormFieldDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "example": "order_number",
            "pattern": "^[a-z][a-z0-9_]{0,31}$"
          },
          "label": {
            "type": "string",
            "example": "Order number",
            "maxLength": 60
          },
          "type": {
            "type": "string",
            "enum": ["text", "email", "tel", "textarea", "select"]
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "description": "Choices for `select` fields (1–20)",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["key", "label", "type", "required"]
      },
      "WidgetFormDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "message": {
            "type": "string",
            "maxLength": 300,
            "description": "Intro text; send \"\" to remove it"
          },
          "fields": {
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FormFieldDto"
            }
          }
        }
      },
      "TimePeriodDto": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "example": "09:00",
            "description": "HH:MM in the business-hours timezone"
          },
          "end": {
            "type": "string",
            "example": "17:00",
            "description": "HH:MM, after start (24:00 = end of day)"
          }
        },
        "required": ["start", "end"]
      },
      "WeeklyHoursDto": {
        "type": "object",
        "properties": {
          "mon": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "tue": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "wed": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "thu": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "fri": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "sat": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          },
          "sun": {
            "maxItems": 6,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimePeriodDto"
            }
          }
        }
      },
      "BusinessHoursDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Off = always open (agent presence still applies)"
          },
          "timezone": {
            "type": "string",
            "example": "Europe/Berlin",
            "description": "IANA timezone"
          },
          "weekly": {
            "$ref": "#/components/schemas/WeeklyHoursDto"
          },
          "holidays": {
            "example": ["2026-12-25"],
            "description": "Closed all day (YYYY-MM-DD in the timezone)",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ConsentSettingsDto": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["off", "manual", "regional"],
            "description": "`off`: no consent handling. `manual`: nothing optional is stored or tracked until the page calls ZebChat.consent(true). `regional`: rules by the visitor's region (Europe opt-in, US opt-out, the rest as `other`), with the widget's own prompt"
          },
          "us": {
            "type": "string",
            "enum": ["opt_out", "opt_in"],
            "description": "Regional: US visitors (`opt_out` = CCPA/CPRA default, `opt_in` = stricter)"
          },
          "other": {
            "type": "string",
            "enum": ["opt_in", "opt_out", "none"],
            "description": "Regional: visitors outside Europe and the US. Europe is always `opt_in`"
          },
          "unknown": {
            "type": "string",
            "enum": ["strict", "other"],
            "description": "Regional: unknown country → `strict` (opt-in) or the `other` rule"
          },
          "gpc": {
            "type": "boolean",
            "description": "Honour Global Privacy Control as an opt-out (opt-out and no-consent regions)"
          },
          "prompt": {
            "type": "boolean",
            "description": "The widget's own consent prompt for opt-in visitors (off when your banner calls ZebChat.consent())"
          },
          "notice": {
            "type": "boolean",
            "description": "Also a discreet notice above the closed launcher until opt-in visitors answer"
          },
          "optOutLink": {
            "type": "boolean",
            "description": "\"Do Not Sell or Share My Info\" in the widget menu for opt-out visitors"
          }
        }
      },
      "PrivacySettingsDto": {
        "type": "object",
        "properties": {
          "policyUrl": {
            "type": "string",
            "nullable": true,
            "example": "https://example.com/privacy",
            "description": "https URL of your privacy policy; null removes it"
          },
          "notice": {
            "type": "string",
            "maxLength": 300,
            "description": "Short notice at the bottom of the chat panel ('' = none)"
          },
          "requireAgreement": {
            "type": "boolean",
            "description": "Visitors tick \"I agree to the privacy policy\" before their first message (needs policyUrl)"
          }
        }
      },
      "WidgetNotificationsDto": {
        "type": "object",
        "properties": {
          "sound": {
            "type": "boolean",
            "description": "New-message chime for visitors. Off: no sound and no Sound item in the widget menu"
          },
          "previewDesktop": {
            "type": "boolean",
            "description": "Desktop: agent messages that arrive while the panel is closed show in a preview bubble"
          },
          "previewMobile": {
            "type": "boolean",
            "description": "Phones and tablets: the same preview bubble"
          },
          "agentTyping": {
            "type": "boolean",
            "description": "Visitors see \"… is typing\" while an agent writes (off: agent typing is not relayed)"
          },
          "visitorTyping": {
            "type": "boolean",
            "description": "Agents see visitors typing, with a live text preview (sneak peek). Off: the widget sends nothing and the API relays nothing"
          },
          "tabTitle": {
            "type": "boolean",
            "description": "Background tab: the page title flashes \"(1) New message\" until the visitor looks"
          },
          "hideWaitTime": {
            "type": "boolean",
            "description": "The waiting card shows the place in line only, without the estimated wait"
          }
        }
      },
      "UrlRuleDto": {
        "type": "object",
        "properties": {
          "match": {
            "type": "string",
            "enum": ["contains", "starts_with", "exact", "wildcard"]
          },
          "value": {
            "type": "string",
            "example": "/checkout",
            "maxLength": 500,
            "description": "Case-insensitive. Starts with \"/\": compared with the path (+ query and hash), else with the full URL. `wildcard`: * matches anything"
          }
        },
        "required": ["match", "value"]
      },
      "UrlRulesDto": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["off", "show", "hide"],
            "description": "`show`: only on pages matching a rule; `hide`: everywhere except those"
          },
          "rules": {
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UrlRuleDto"
            }
          }
        }
      },
      "CountryRulesDto": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["off", "show", "hide"],
            "description": "`show`: only for visitors from these countries; `hide`: for everyone else. Needs visitor location (`geoAvailable`); unknown countries are never listed"
          },
          "countries": {
            "example": ["DE", "AT"],
            "maxItems": 250,
            "description": "ISO 3166-1 alpha-2 codes",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WidgetVisibilityDto": {
        "type": "object",
        "properties": {
          "hideWhenOffline": {
            "type": "boolean",
            "description": "No launcher at all while nobody is available (instead of the offline form)"
          },
          "platforms": {
            "type": "array",
            "description": "Devices that show the widget (at least one)",
            "items": {
              "type": "string",
              "enum": ["desktop", "tablet", "mobile"]
            }
          },
          "urlRules": {
            "description": "Show/hide by page URL (in the browser)",
            "allOf": [
              {
                "$ref": "#/components/schemas/UrlRulesDto"
              }
            ]
          },
          "countries": {
            "description": "Show/hide by the visitor's country (decided by the API)",
            "allOf": [
              {
                "$ref": "#/components/schemas/CountryRulesDto"
              }
            ]
          }
        }
      },
      "WidgetFeaturesDto": {
        "type": "object",
        "properties": {
          "emoji": {
            "type": "boolean",
            "description": "Emoji picker in the composer"
          },
          "uploads": {
            "type": "boolean",
            "description": "Visitors can send files. Off: no attach button, and visitor uploads are refused (403)"
          }
        }
      },
      "WidgetSettingsDto": {
        "type": "object",
        "properties": {
          "color": {
            "type": "string",
            "example": "#0154F9",
            "description": "Brand color, #RRGGBB"
          },
          "position": {
            "type": "string",
            "enum": ["left", "right"]
          },
          "offsetX": {
            "type": "number",
            "minimum": 0,
            "maximum": 200,
            "description": "px from the side edge"
          },
          "offsetY": {
            "type": "number",
            "minimum": 0,
            "maximum": 200,
            "description": "px from the bottom"
          },
          "launcher": {
            "$ref": "#/components/schemas/LauncherDto"
          },
          "theme": {
            "type": "string",
            "enum": ["light", "dark", "auto"]
          },
          "style": {
            "type": "string",
            "enum": ["classic", "soft", "minimal", "compact"]
          },
          "language": {
            "type": "string",
            "enum": ["auto", "en", "hi", "es", "ar", "pt", "fr", "de"],
            "description": "Language of the widget's own texts; `auto` = the visitor's browser language when supported, else English"
          },
          "title": {
            "type": "string",
            "example": "Chat with us",
            "maxLength": 60
          },
          "greeting": {
            "type": "string",
            "example": "Hi there 👋 How can we help you today?",
            "maxLength": 300
          },
          "agentAvatar": {
            "type": "string",
            "nullable": true,
            "description": "https image URL"
          },
          "showPoweredBy": {
            "type": "boolean"
          },
          "preChat": {
            "description": "Asked before the first message",
            "allOf": [
              {
                "$ref": "#/components/schemas/WidgetFormDto"
              }
            ]
          },
          "offlineForm": {
            "description": "Shown while nobody is available",
            "allOf": [
              {
                "$ref": "#/components/schemas/WidgetFormDto"
              }
            ]
          },
          "businessHours": {
            "$ref": "#/components/schemas/BusinessHoursDto"
          },
          "spamProtection": {
            "type": "string",
            "enum": ["off", "turnstile"]
          },
          "cookieConsent": {
            "type": "string",
            "enum": ["off", "required"],
            "description": "Legacy mirror of `consent.mode` (`off` → off, otherwise `required`)"
          },
          "consent": {
            "$ref": "#/components/schemas/ConsentSettingsDto"
          },
          "privacy": {
            "$ref": "#/components/schemas/PrivacySettingsDto"
          },
          "transcripts": {
            "type": "string",
            "enum": ["off", "visitor"],
            "description": "`visitor`: visitors can email themselves a transcript of their chat"
          },
          "showTeamFaces": {
            "type": "boolean",
            "description": "Before an agent joins, the widget header shows up to 3 agents online now (first names and photos)"
          },
          "ratings": {
            "type": "boolean",
            "description": "Ask visitors to rate the chat when it ends; `false` hides the rating card and refuses ratings (403)"
          },
          "notifications": {
            "$ref": "#/components/schemas/WidgetNotificationsDto"
          },
          "visibility": {
            "$ref": "#/components/schemas/WidgetVisibilityDto"
          },
          "features": {
            "$ref": "#/components/schemas/WidgetFeaturesDto"
          },
          "onClick": {
            "type": "string",
            "enum": ["maximize", "popout"],
            "description": "Launcher click: open the panel, or the chat in a new window with the same conversation (`ZebChat.open()` always opens the panel)"
          }
        },
        "required": [
          "color",
          "position",
          "offsetX",
          "offsetY",
          "launcher",
          "theme",
          "style",
          "language",
          "title",
          "greeting",
          "agentAvatar",
          "showPoweredBy",
          "preChat",
          "offlineForm",
          "businessHours",
          "spamProtection",
          "cookieConsent",
          "consent",
          "privacy",
          "transcripts",
          "showTeamFaces",
          "ratings",
          "notifications",
          "visibility",
          "features",
          "onClick"
        ]
      },
      "WebsiteSkillFieldDto": {
        "type": "object",
        "properties": {
          "fieldKey": {
            "type": "string",
            "example": "topic",
            "description": "Key of a select field in the pre-chat form"
          },
          "options": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "Billing question": "skl_…"
            },
            "description": "Option → skill id. Other answers (or none) use the website's default skill"
          }
        },
        "required": ["fieldKey", "options"]
      },
      "WebsiteDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string"
          },
          "domain": {
            "type": "string",
            "example": "example.com"
          },
          "allowedDomains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "siteKey": {
            "type": "string",
            "example": "zc_8kQ2…",
            "description": "Public key used in the embed snippet"
          },
          "settings": {
            "$ref": "#/components/schemas/WidgetSettingsDto"
          },
          "defaultTeamId": {
            "type": "string",
            "nullable": true,
            "example": "team_…"
          },
          "defaultSkillId": {
            "type": "string",
            "nullable": true,
            "example": "skl_…"
          },
          "skillField": {
            "nullable": true,
            "description": "Pick the required skill from a pre-chat answer (null = off)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/WebsiteSkillFieldDto"
              }
            ]
          },
          "identityVerification": {
            "type": "boolean",
            "description": "An identity secret is set: `setUser` hashes are verified"
          },
          "turnstileAvailable": {
            "type": "boolean",
            "description": "The server has Turnstile configured, so `spamProtection: turnstile` can be used"
          },
          "geoAvailable": {
            "type": "boolean",
            "description": "The server knows visitors' countries (GEO_SOURCE), so `settings.visibility.countries` applies; otherwise country rules are stored but not enforced"
          },
          "installSnippet": {
            "type": "string",
            "description": "HTML to paste before </body>"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "domain",
          "allowedDomains",
          "siteKey",
          "settings",
          "defaultTeamId",
          "defaultSkillId",
          "skillField",
          "identityVerification",
          "turnstileAvailable",
          "geoAvailable",
          "installSnippet",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateWebsiteDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Example Store"
          },
          "domain": {
            "type": "string",
            "example": "example.com",
            "description": "Primary domain; a URL is accepted and reduced to its hostname"
          },
          "allowedDomains": {
            "example": ["staging.example.net", "*.preview.example.org", "localhost"],
            "description": "Extra hostnames allowed to load the widget (subdomains included; `*.` = subdomains only)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "defaultTeamId": {
            "type": "string",
            "nullable": true,
            "example": "team_…",
            "description": "Route new chats to this team (null = everyone)"
          },
          "defaultSkillId": {
            "type": "string",
            "nullable": true,
            "example": "skl_…",
            "description": "Skill new chats from this website need (skills routing; null = none)"
          }
        },
        "required": ["name", "domain"]
      },
      "UpdateWidgetSettingsDto": {
        "type": "object",
        "properties": {
          "color": {
            "type": "string",
            "example": "#0154F9"
          },
          "position": {
            "type": "string",
            "enum": ["left", "right"]
          },
          "language": {
            "type": "string",
            "enum": ["auto", "en", "hi", "es", "ar", "pt", "fr", "de"],
            "description": "Language of the widget's own texts; `auto` = the visitor's browser language when supported, else English"
          },
          "offsetX": {
            "type": "number",
            "minimum": 0,
            "maximum": 200
          },
          "offsetY": {
            "type": "number",
            "minimum": 0,
            "maximum": 200
          },
          "launcher": {
            "$ref": "#/components/schemas/LauncherDto"
          },
          "theme": {
            "type": "string",
            "enum": ["light", "dark", "auto"]
          },
          "style": {
            "type": "string",
            "enum": ["classic", "soft", "minimal", "compact"]
          },
          "title": {
            "type": "string",
            "maxLength": 60
          },
          "greeting": {
            "type": "string",
            "maxLength": 300
          },
          "agentAvatar": {
            "type": "string",
            "nullable": true,
            "description": "https URL; null removes it"
          },
          "showPoweredBy": {
            "type": "boolean"
          },
          "preChat": {
            "$ref": "#/components/schemas/WidgetFormDto"
          },
          "offlineForm": {
            "$ref": "#/components/schemas/WidgetFormDto"
          },
          "businessHours": {
            "$ref": "#/components/schemas/BusinessHoursDto"
          },
          "spamProtection": {
            "type": "string",
            "enum": ["off", "turnstile"],
            "description": "`turnstile` needs Turnstile configured on the server (`turnstileAvailable`)"
          },
          "cookieConsent": {
            "type": "string",
            "enum": ["off", "required"],
            "description": "Legacy: `required` = `consent.mode: manual` (or keeps the current non-off mode), `off` = `consent.mode: off`. Ignored when `consent.mode` is sent"
          },
          "consent": {
            "$ref": "#/components/schemas/ConsentSettingsDto"
          },
          "privacy": {
            "$ref": "#/components/schemas/PrivacySettingsDto"
          },
          "transcripts": {
            "type": "string",
            "enum": ["off", "visitor"],
            "description": "`visitor`: visitors can email themselves a transcript of their chat"
          },
          "showTeamFaces": {
            "type": "boolean",
            "description": "Before an agent joins, the widget header shows up to 3 agents online now (first names and photos)"
          },
          "ratings": {
            "type": "boolean",
            "description": "Ask visitors to rate the chat when it ends; `false` hides the rating card and refuses ratings (403)"
          },
          "notifications": {
            "$ref": "#/components/schemas/WidgetNotificationsDto"
          },
          "visibility": {
            "$ref": "#/components/schemas/WidgetVisibilityDto"
          },
          "features": {
            "$ref": "#/components/schemas/WidgetFeaturesDto"
          },
          "onClick": {
            "type": "string",
            "enum": ["maximize", "popout"],
            "description": "Launcher click: open the panel, or the chat in a new window with the same conversation (`ZebChat.open()` always opens the panel)"
          }
        }
      },
      "UpdateWebsiteDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Example Store"
          },
          "domain": {
            "type": "string",
            "example": "example.com"
          },
          "allowedDomains": {
            "example": ["staging.example.net", "*.preview.example.org", "localhost"],
            "description": "Extra hostnames allowed to load the widget (subdomains included; `*.` = subdomains only)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "settings": {
            "$ref": "#/components/schemas/UpdateWidgetSettingsDto"
          },
          "defaultTeamId": {
            "type": "string",
            "nullable": true,
            "example": "team_…",
            "description": "Route new chats to this team (null = everyone)"
          },
          "defaultSkillId": {
            "type": "string",
            "nullable": true,
            "example": "skl_…",
            "description": "Skill new chats from this website need (skills routing; null = none)"
          },
          "skillField": {
            "nullable": true,
            "description": "Pick the required skill from a pre-chat answer (null = off)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/WebsiteSkillFieldDto"
              }
            ]
          }
        }
      },
      "IdentitySecretStatusDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether `setUser` hashes are verified for this website"
          }
        },
        "required": ["enabled"]
      },
      "IdentitySecretDto": {
        "type": "object",
        "properties": {
          "secret": {
            "type": "string",
            "example": "3f9c…",
            "description": "Shown once. Keep it on your server: hash = hex(HMAC-SHA256(secret, userId)). Rotating invalidates old hashes"
          }
        },
        "required": ["secret"]
      },
      "TimeZoneDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "Asia/Kolkata"
          },
          "label": {
            "type": "string",
            "example": "(UTC+05:30) Asia/Kolkata · India Standard Time"
          },
          "offsetMinutes": {
            "type": "number",
            "example": 330,
            "description": "Current offset from UTC in minutes (DST included)"
          }
        },
        "required": ["id", "label", "offsetMinutes"]
      },
      "BrandingDto": {
        "type": "object",
        "properties": {
          "showPoweredBy": {
            "type": "boolean"
          }
        },
        "required": ["showPoweredBy"]
      },
      "WidgetAgentFaceDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Opaque key, stable per website and agent (not an id)"
          },
          "name": {
            "type": "string",
            "example": "Olivia",
            "description": "First name only"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "Profile photo URL"
          }
        },
        "required": ["key", "name", "avatarUrl"]
      },
      "WidgetAvailabilityDto": {
        "type": "object",
        "properties": {
          "online": {
            "type": "boolean",
            "description": "Visitors can chat now (else show the offline form)"
          },
          "reason": {
            "type": "string",
            "enum": ["business_hours", "no_agents"],
            "nullable": true
          },
          "nextOpenAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Next opening when closed by business hours"
          },
          "faces": {
            "description": "Up to 3 agents online now for this website (its default team, if set); empty while offline or when the website's showTeamFaces is off",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WidgetAgentFaceDto"
            }
          }
        },
        "required": ["online", "reason", "nextOpenAt", "faces"]
      },
      "WidgetConsentDto": {
        "type": "object",
        "properties": {
          "region": {
            "type": "string",
            "enum": ["eu", "us", "other", "unknown"],
            "description": "From the visitor's country: `eu` (EU/EEA, UK, Switzerland), `us`, `other`, or `unknown`"
          },
          "requirement": {
            "type": "string",
            "enum": ["opt_in", "opt_out", "none"],
            "description": "What the website's consent policy requires for this visitor (`none` while consent handling is off; `opt_in` in `manual` mode)"
          },
          "version": {
            "type": "string",
            "example": "3f9c0a1b2c3d4e5f",
            "description": "Version of the website's consent settings: remembered decisions from another version are asked again"
          }
        },
        "required": ["region", "requirement", "version"]
      },
      "WidgetConfigDto": {
        "type": "object",
        "properties": {
          "siteKey": {
            "type": "string"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string"
          },
          "settings": {
            "$ref": "#/components/schemas/WidgetSettingsDto"
          },
          "branding": {
            "description": "Mirrors settings.showPoweredBy",
            "allOf": [
              {
                "$ref": "#/components/schemas/BrandingDto"
              }
            ]
          },
          "availability": {
            "$ref": "#/components/schemas/WidgetAvailabilityDto"
          },
          "turnstileSiteKey": {
            "type": "string",
            "nullable": true,
            "description": "Turnstile site key when starting a conversation needs a Turnstile token"
          },
          "attachmentMaxBytes": {
            "type": "number",
            "description": "Largest attachment the API accepts, in bytes"
          },
          "hidden": {
            "type": "boolean",
            "description": "The website's country rules hide the widget from this visitor: show nothing (sessions are refused)"
          },
          "consent": {
            "description": "Consent rules for this visitor",
            "allOf": [
              {
                "$ref": "#/components/schemas/WidgetConsentDto"
              }
            ]
          }
        },
        "required": [
          "siteKey",
          "websiteId",
          "name",
          "settings",
          "branding",
          "availability",
          "turnstileSiteKey",
          "attachmentMaxBytes",
          "hidden",
          "consent"
        ]
      },
      "CreateWidgetSessionDto": {
        "type": "object",
        "properties": {
          "siteKey": {
            "type": "string",
            "example": "zc_8kQ2…"
          },
          "host": {
            "type": "string",
            "example": "https://example.com",
            "description": "Origin of the page embedding the widget"
          },
          "visitorKey": {
            "type": "string",
            "description": "Visitor key from a previous session (stored by the widget)"
          }
        },
        "required": ["siteKey", "host"]
      },
      "WidgetVisitorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "verified": {
            "type": "boolean",
            "description": "Identity proven with a valid setUser hash"
          }
        },
        "required": ["id", "name", "email", "phone", "verified"]
      },
      "WidgetSessionDto": {
        "type": "object",
        "properties": {
          "visitorToken": {
            "type": "string"
          },
          "visitorTokenExpiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "visitorKey": {
            "type": "string",
            "description": "Only when a new visitor was created; store it and send it next time"
          },
          "visitor": {
            "$ref": "#/components/schemas/WidgetVisitorDto"
          },
          "availability": {
            "$ref": "#/components/schemas/WidgetAvailabilityDto"
          }
        },
        "required": ["visitorToken", "visitorTokenExpiresAt", "visitor", "availability"]
      },
      "IdentifyDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "user_123",
            "description": "Your user id (needs `hash`)"
          },
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "hash": {
            "type": "string",
            "example": "9f86d0…",
            "description": "hex(HMAC-SHA256(identitySecret, id)), computed on your server"
          }
        }
      },
      "ConversationVisitorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["id", "name", "email"]
      },
      "ConversationParticipantDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string",
            "enum": ["participant", "monitor"],
            "description": "`participant`: a co-agent who can reply; `monitor`: a supervisor watching silently"
          },
          "addedByUserId": {
            "type": "string",
            "nullable": true,
            "example": "usr_…",
            "description": "Who added them (themselves when they joined or started monitoring)"
          },
          "addedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["userId", "name", "avatarUrl", "role", "addedByUserId", "addedAt"]
      },
      "RequiredSkillDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "skl_…"
          },
          "name": {
            "type": "string",
            "example": "Billing"
          }
        },
        "required": ["id", "name"]
      },
      "TagDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "tag_…"
          },
          "name": {
            "type": "string",
            "example": "billing"
          },
          "color": {
            "type": "string",
            "example": "#64748B"
          }
        },
        "required": ["id", "name", "color"]
      },
      "ConversationRatingDto": {
        "type": "object",
        "properties": {
          "rating": {
            "type": "number",
            "minimum": 1,
            "maximum": 5
          },
          "comment": {
            "type": "string",
            "nullable": true
          },
          "ratedUserId": {
            "type": "string",
            "nullable": true,
            "example": "usr_…",
            "description": "The agent assigned when the visitor first rated (the rating counts for them)"
          },
          "teamId": {
            "type": "string",
            "nullable": true,
            "example": "team_…"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["rating", "comment", "ratedUserId", "teamId", "createdAt", "updatedAt"]
      },
      "ConversationAiStateDto": {
        "type": "object",
        "properties": {
          "active": {
            "type": "boolean",
            "description": "The AI owns the chat; routing leaves it alone until a handoff"
          },
          "turns": {
            "type": "number",
            "description": "AI replies so far"
          },
          "endedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "endReason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "tool",
              "keyword",
              "turn_limit",
              "spend_cap",
              "key_error",
              "refusal",
              "provider_error",
              "human"
            ]
          }
        },
        "required": ["active", "turns", "endedAt", "endReason"]
      },
      "ConversationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "conv_…"
          },
          "status": {
            "type": "string",
            "enum": ["new", "open", "pending", "waiting", "resolved", "closed", "spam"]
          },
          "priority": {
            "type": "string",
            "enum": ["low", "normal", "high", "urgent"]
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "visitor": {
            "$ref": "#/components/schemas/ConversationVisitorDto"
          },
          "assignedUserId": {
            "type": "string",
            "nullable": true,
            "example": "usr_…"
          },
          "assignedUserName": {
            "type": "string",
            "nullable": true
          },
          "assignedUserAvatarUrl": {
            "type": "string",
            "nullable": true
          },
          "assignedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "teamId": {
            "type": "string",
            "nullable": true,
            "example": "team_…"
          },
          "participants": {
            "description": "Agents taking part besides the assignee: co-agents (`participant`) and silent monitors (`monitor`), oldest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationParticipantDto"
            }
          },
          "requiredSkill": {
            "nullable": true,
            "description": "Skill an agent needs for this chat (skills routing), set when it started",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/RequiredSkillDto"
              }
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagDto"
            }
          },
          "offline": {
            "type": "boolean",
            "description": "Left through the offline form (nobody was available)"
          },
          "formData": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Pre-chat / offline form answers by field key ({} if none)"
          },
          "lastSeq": {
            "type": "number"
          },
          "lastMessageAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastMessagePreview": {
            "type": "string",
            "nullable": true
          },
          "agentUnreadCount": {
            "type": "number",
            "description": "Visitor messages no agent has read yet"
          },
          "visitorReadSeq": {
            "type": "number",
            "description": "Highest seq the visitor has read (0 = none)"
          },
          "visitorDeliveredSeq": {
            "type": "number",
            "description": "Highest seq delivered to the visitor (0 = none)"
          },
          "visitorUnreadCount": {
            "type": "number",
            "description": "Agent messages the visitor has not read yet"
          },
          "firstResponseAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "resolvedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "closedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "rating": {
            "nullable": true,
            "description": "The visitor's post-chat rating, if any",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ConversationRatingDto"
              }
            ]
          },
          "ai": {
            "nullable": true,
            "description": "The AI assistant on this chat (null when it never took part)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ConversationAiStateDto"
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "priority",
          "websiteId",
          "visitor",
          "assignedUserId",
          "assignedUserName",
          "assignedUserAvatarUrl",
          "assignedAt",
          "teamId",
          "participants",
          "requiredSkill",
          "tags",
          "offline",
          "formData",
          "lastSeq",
          "lastMessageAt",
          "lastMessagePreview",
          "agentUnreadCount",
          "visitorReadSeq",
          "visitorDeliveredSeq",
          "visitorUnreadCount",
          "firstResponseAt",
          "resolvedAt",
          "closedAt",
          "rating",
          "ai",
          "createdAt",
          "updatedAt"
        ]
      },
      "ConversationPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "StatusCountsDto": {
        "type": "object",
        "properties": {
          "new": {
            "type": "number"
          },
          "open": {
            "type": "number"
          },
          "pending": {
            "type": "number"
          },
          "waiting": {
            "type": "number"
          }
        },
        "required": ["new", "open", "pending", "waiting"]
      },
      "ConversationCountsDto": {
        "type": "object",
        "properties": {
          "active": {
            "type": "number",
            "description": "Active conversations (new, open, pending, waiting)"
          },
          "unassigned": {
            "type": "number",
            "description": "Active and not assigned (the queue)"
          },
          "mine": {
            "type": "number",
            "description": "Active and assigned to you, or you take part as a co-agent"
          },
          "unread": {
            "type": "number",
            "description": "Active with visitor messages no agent has read"
          },
          "byStatus": {
            "$ref": "#/components/schemas/StatusCountsDto"
          }
        },
        "required": ["active", "unassigned", "mine", "unread", "byStatus"]
      },
      "UpdateConversationDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["open", "resolved", "closed"]
          },
          "priority": {
            "type": "string",
            "enum": ["low", "normal", "high", "urgent"]
          }
        }
      },
      "ChatSenderDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_… or vis_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "Agents' profile photo"
          }
        },
        "required": ["id", "name", "avatarUrl"]
      },
      "ChatAttachmentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "att_…"
          },
          "fileName": {
            "type": "string",
            "example": "invoice.pdf"
          },
          "contentType": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "image/gif",
              "image/webp",
              "application/pdf",
              "text/plain",
              "text/csv",
              "application/msword",
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
              "application/vnd.ms-excel",
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
              "application/zip"
            ]
          },
          "sizeBytes": {
            "type": "number"
          },
          "isImage": {
            "type": "boolean",
            "description": "Images can be shown inline"
          },
          "url": {
            "type": "string",
            "description": "Signed download link (no auth header needed)"
          },
          "urlExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Refetch the message after this"
          },
          "thumbnailUrl": {
            "type": "string",
            "nullable": true,
            "description": "Images: signed link to a WebP preview (≤ 320 px wide), or the full image while it is being made. Null for other files"
          }
        },
        "required": [
          "id",
          "fileName",
          "contentType",
          "sizeBytes",
          "isImage",
          "url",
          "urlExpiresAt",
          "thumbnailUrl"
        ]
      },
      "ChatMessageDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "msg_…"
          },
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "seq": {
            "type": "number",
            "description": "Per-conversation sequence, strictly increasing"
          },
          "senderType": {
            "type": "string",
            "enum": ["visitor", "agent", "ai", "system", "bot"]
          },
          "sender": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ChatSenderDto"
              }
            ]
          },
          "body": {
            "type": "string",
            "description": "May be empty when the message only carries attachments"
          },
          "isInternal": {
            "type": "boolean",
            "description": "Internal notes are only ever sent to agents"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatAttachmentDto"
            }
          },
          "clientMessageId": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "event": {
            "type": "object",
            "additionalProperties": true,
            "description": "System messages only: what changed (`type`: status, reopened, assigned, unassigned, transferred, priority, participant_added, participant_removed, monitoring, ai_handoff). See ConversationEvent in docs/API.md",
            "example": {
              "type": "status",
              "from": "open",
              "to": "resolved",
              "actor": {
                "id": "usr_…",
                "name": "Olivia Owner"
              }
            }
          },
          "ai": {
            "type": "object",
            "additionalProperties": true,
            "description": "AI messages, agents only: {provider, model, usage, costMicros, sources}. Never sent to visitors"
          },
          "aiConfirm": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "action": "Cancel order"
            },
            "description": "AI messages that ask the visitor to confirm a customer action (visitor and agents)"
          },
          "via": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "type": "mcp",
              "apiKeyId": "key_…",
              "name": "Claude Desktop"
            },
            "description": "Agents only: sent (or, on system messages, done) with an API key. `type`: `api` (REST) or `mcp` (an AI app through the MCP server). `sender` is the member who created the key"
          },
          "automation": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "ruleId": "aut_…",
              "ruleName": "Tag pricing questions"
            },
            "description": "Agents only: the automation that sent this message (`senderType: bot`, or an internal note) or made this change (system messages)"
          }
        },
        "required": [
          "id",
          "conversationId",
          "seq",
          "senderType",
          "sender",
          "body",
          "isInternal",
          "attachments",
          "clientMessageId",
          "createdAt"
        ]
      },
      "MessagePageDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Ascending by seq",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessageDto"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "More messages exist in the requested direction"
          }
        },
        "required": ["data", "hasMore"]
      },
      "AgentSendMessageDto": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 5000,
            "example": "Hi! Do you ship to Canada?",
            "description": "May be empty (\"\") only when attachmentIds are sent"
          },
          "attachmentIds": {
            "example": ["att_…"],
            "maxItems": 10,
            "description": "Uploaded attachments to send with this message",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientMessageId": {
            "type": "string",
            "example": "c_8f2k1x9q",
            "description": "Client-generated idempotency key (8–64 chars [A-Za-z0-9_-]); retries return the original message"
          },
          "internal": {
            "type": "boolean",
            "description": "An internal note: only agents ever see it"
          }
        },
        "required": ["body", "clientMessageId"]
      },
      "SetTagsDto": {
        "type": "object",
        "properties": {
          "tagIds": {
            "example": ["tag_…"],
            "description": "Replaces the tags",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["tagIds"]
      },
      "CreateAttachmentDto": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "example": "invoice.pdf",
            "maxLength": 200
          },
          "contentType": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "image/gif",
              "image/webp",
              "application/pdf",
              "text/plain",
              "text/csv",
              "application/msword",
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
              "application/vnd.ms-excel",
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
              "application/zip"
            ]
          },
          "sizeBytes": {
            "type": "number",
            "description": "Exact size in bytes (the upload must match it)"
          }
        },
        "required": ["fileName", "contentType", "sizeBytes"]
      },
      "AttachmentUploadDto": {
        "type": "object",
        "properties": {
          "attachmentId": {
            "type": "string",
            "example": "att_…"
          },
          "uploadUrl": {
            "type": "string",
            "description": "PUT the raw file bytes here"
          },
          "method": {
            "type": "string",
            "enum": ["PUT"]
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Send these headers with the PUT (they are signed)"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["attachmentId", "uploadUrl", "method", "headers", "expiresAt"]
      },
      "ReceiptDto": {
        "type": "object",
        "properties": {
          "messageId": {
            "type": "string",
            "example": "msg_…",
            "description": "Latest message the participant has read/received"
          }
        },
        "required": ["messageId"]
      },
      "AssignDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "nullable": true,
            "example": "usr_…",
            "description": "null unassigns (back to the queue)"
          }
        },
        "required": ["userId"]
      },
      "TransferDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "teamId": {
            "type": "string",
            "example": "team_…"
          },
          "note": {
            "type": "string",
            "maxLength": 500,
            "description": "Context for the next agent (shown in the audit log)"
          }
        }
      },
      "MessageHitDto": {
        "type": "object",
        "properties": {
          "messageId": {
            "type": "string",
            "example": "msg_…"
          },
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "seq": {
            "type": "number"
          },
          "senderType": {
            "type": "string",
            "enum": ["visitor", "agent", "ai", "system", "bot"]
          },
          "isInternal": {
            "type": "boolean"
          },
          "snippet": {
            "type": "string",
            "description": "Matching excerpt; matches are wrapped in <mark></mark>, other text is escaped"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "visitor": {
            "$ref": "#/components/schemas/ConversationVisitorDto"
          }
        },
        "required": [
          "messageId",
          "conversationId",
          "seq",
          "senderType",
          "isInternal",
          "snippet",
          "createdAt",
          "visitor"
        ]
      },
      "MessageSearchPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageHitDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "SendMessageDto": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 5000,
            "example": "Hi! Do you ship to Canada?",
            "description": "May be empty (\"\") only when attachmentIds are sent"
          },
          "attachmentIds": {
            "example": ["att_…"],
            "maxItems": 10,
            "description": "Uploaded attachments to send with this message",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientMessageId": {
            "type": "string",
            "example": "c_8f2k1x9q",
            "description": "Client-generated idempotency key (8–64 chars [A-Za-z0-9_-]); retries return the original message"
          }
        },
        "required": ["body", "clientMessageId"]
      },
      "StartConversationDto": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 5000,
            "example": "Hi! Do you ship to Canada?",
            "description": "May be empty (\"\") only when attachmentIds are sent"
          },
          "attachmentIds": {
            "example": ["att_…"],
            "maxItems": 10,
            "description": "Uploaded attachments to send with this message",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "clientMessageId": {
            "type": "string",
            "example": "c_8f2k1x9q",
            "description": "Client-generated idempotency key (8–64 chars [A-Za-z0-9_-]); retries return the original message"
          },
          "formData": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "name": "Ana",
              "email": "ana@example.com"
            },
            "description": "Answers to the website's pre-chat form (or offline form when `offline`), by field key"
          },
          "offline": {
            "type": "boolean",
            "description": "Sent through the offline form (nobody was available)"
          },
          "turnstileToken": {
            "type": "string",
            "description": "Cloudflare Turnstile token, required when the widget config has a turnstileSiteKey"
          },
          "privacyAccepted": {
            "type": "boolean",
            "description": "The visitor ticked \"I agree to the privacy policy\"; required when the website settings have `privacy.requireAgreement` on (logged in the consent log)"
          }
        },
        "required": ["body", "clientMessageId"]
      },
      "VisitorConversationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "conv_…"
          },
          "status": {
            "type": "string",
            "enum": ["new", "open", "pending", "waiting", "resolved", "closed", "spam"]
          },
          "lastSeq": {
            "type": "number"
          },
          "visitorUnreadCount": {
            "type": "number"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "queuePosition": {
            "type": "number",
            "nullable": true,
            "description": "Place in line while waiting for an agent (1 = next)"
          },
          "estimatedWaitSeconds": {
            "type": "number",
            "nullable": true
          },
          "assignedAgentName": {
            "type": "string",
            "nullable": true,
            "description": "Name of the agent handling the chat"
          },
          "assignedAgentAvatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "That agent's profile photo"
          }
        },
        "required": [
          "id",
          "status",
          "lastSeq",
          "visitorUnreadCount",
          "createdAt",
          "queuePosition",
          "estimatedWaitSeconds",
          "assignedAgentName",
          "assignedAgentAvatarUrl"
        ]
      },
      "StartConversationResponseDto": {
        "type": "object",
        "properties": {
          "conversation": {
            "$ref": "#/components/schemas/VisitorConversationDto"
          },
          "message": {
            "$ref": "#/components/schemas/ChatMessageDto"
          }
        },
        "required": ["conversation", "message"]
      },
      "AddParticipantDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "example": "usr_…",
            "description": "The agent to add (yourself: join the chat, needs conversations:supervise)"
          }
        },
        "required": ["userId"]
      },
      "CurrentPageDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "since": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["url", "title", "since"]
      },
      "UtmDto": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "nullable": true
          },
          "medium": {
            "type": "string",
            "nullable": true
          },
          "campaign": {
            "type": "string",
            "nullable": true
          },
          "term": {
            "type": "string",
            "nullable": true
          },
          "content": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["source", "medium", "campaign", "term", "content"]
      },
      "VisitSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vst_…"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "pageCount": {
            "type": "number"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "IN"
          },
          "region": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "browser": {
            "type": "string",
            "nullable": true,
            "example": "Chrome"
          },
          "browserVersion": {
            "type": "string",
            "nullable": true
          },
          "os": {
            "type": "string",
            "nullable": true,
            "example": "Windows 10"
          },
          "deviceType": {
            "type": "string",
            "nullable": true,
            "enum": ["desktop", "mobile", "tablet", "bot"]
          },
          "referrer": {
            "type": "string",
            "nullable": true
          },
          "landingUrl": {
            "type": "string",
            "nullable": true
          },
          "utm": {
            "$ref": "#/components/schemas/UtmDto"
          }
        },
        "required": [
          "id",
          "startedAt",
          "lastSeenAt",
          "pageCount",
          "country",
          "region",
          "city",
          "browser",
          "browserVersion",
          "os",
          "deviceType",
          "referrer",
          "landingUrl",
          "utm"
        ]
      },
      "VisitorLocationDto": {
        "type": "object",
        "properties": {
          "latitude": {
            "type": "number",
            "example": 12.972
          },
          "longitude": {
            "type": "number",
            "example": 77.594
          },
          "precise": {
            "type": "boolean",
            "description": "City-level (edge geolocation) or the centre of the country"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "IN"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "example": "Bengaluru"
          }
        },
        "required": ["latitude", "longitude", "precise", "country", "city"]
      },
      "LiveVisitorDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string",
            "example": "vis_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "onlineSince": {
            "type": "string",
            "format": "date-time"
          },
          "currentPage": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/CurrentPageDto"
              }
            ]
          },
          "visit": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/VisitSummaryDto"
              }
            ]
          },
          "location": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/VisitorLocationDto"
              }
            ]
          }
        },
        "required": [
          "visitorId",
          "websiteId",
          "name",
          "email",
          "onlineSince",
          "currentPage",
          "visit",
          "location"
        ]
      },
      "LivePageCountDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "count": {
            "type": "number"
          }
        },
        "required": ["url", "title", "count"]
      },
      "LiveVisitorsDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number",
            "description": "Everyone online right now"
          },
          "visitors": {
            "description": "Most recently arrived first, up to `limit`",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LiveVisitorDto"
            }
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LivePageCountDto"
            }
          }
        },
        "required": ["total", "visitors", "pages"]
      },
      "VisitorListItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "externalId": {
            "type": "string",
            "nullable": true,
            "description": "Your user id from a verified setUser"
          },
          "verified": {
            "type": "boolean",
            "description": "Identity proven with a setUser HMAC (name/email otherwise unverified)"
          },
          "online": {
            "type": "boolean"
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "websiteId",
          "name",
          "email",
          "externalId",
          "verified",
          "online",
          "firstSeenAt",
          "lastSeenAt"
        ]
      },
      "VisitorPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VisitorListItemDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "VisitorStatsDto": {
        "type": "object",
        "properties": {
          "visits": {
            "type": "number"
          },
          "pageviews": {
            "type": "number"
          },
          "conversations": {
            "type": "number"
          }
        },
        "required": ["visits", "pageviews", "conversations"]
      },
      "VisitorConversationSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "conv_…"
          },
          "status": {
            "type": "string"
          },
          "lastMessageAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastMessagePreview": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "status", "lastMessageAt", "lastMessagePreview", "createdAt"]
      },
      "VisitorContactDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ctc_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "company": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["id", "name", "email", "company"]
      },
      "VisitorProfileDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "externalId": {
            "type": "string",
            "nullable": true,
            "description": "Your user id from a verified setUser"
          },
          "verified": {
            "type": "boolean",
            "description": "Identity proven with a setUser HMAC (name/email otherwise unverified)"
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "online": {
            "type": "boolean"
          },
          "currentPage": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/CurrentPageDto"
              }
            ]
          },
          "latestVisit": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/VisitSummaryDto"
              }
            ]
          },
          "stats": {
            "$ref": "#/components/schemas/VisitorStatsDto"
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagDto"
            }
          },
          "conversations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VisitorConversationSummaryDto"
            }
          },
          "contact": {
            "nullable": true,
            "description": "The contact this visitor is linked to (null: none yet)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/VisitorContactDto"
              }
            ]
          }
        },
        "required": [
          "id",
          "websiteId",
          "name",
          "email",
          "phone",
          "externalId",
          "verified",
          "firstSeenAt",
          "lastSeenAt",
          "online",
          "currentPage",
          "latestVisit",
          "stats",
          "tags",
          "conversations",
          "contact"
        ]
      },
      "VisitOptionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vst_…"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "pageCount": {
            "type": "number"
          }
        },
        "required": ["id", "startedAt", "pageCount"]
      },
      "JourneyDto": {
        "type": "object",
        "properties": {
          "visit": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/VisitSummaryDto"
              }
            ]
          },
          "items": {
            "type": "array",
            "description": "Ascending by time. `type` is pageview | event | conversation",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "visits": {
            "description": "Recent visits, newest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VisitOptionDto"
            }
          }
        },
        "required": ["visit", "items", "visits"]
      },
      "PageviewDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "example": "https://shop.example/pricing?utm_source=google"
          },
          "title": {
            "type": "string",
            "example": "Pricing – Shop"
          },
          "referrer": {
            "type": "string",
            "example": "https://www.google.com/"
          }
        },
        "required": ["url"]
      },
      "TrackEventDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "checkout_started",
            "pattern": "^[A-Za-z0-9_.:-]{1,64}$"
          },
          "properties": {
            "type": "object",
            "additionalProperties": true,
            "description": "Up to 2 KB of JSON"
          }
        },
        "required": ["name"]
      },
      "CreateTagDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "billing",
            "maxLength": 40
          },
          "color": {
            "type": "string",
            "example": "#64748B",
            "default": "#64748B"
          }
        },
        "required": ["name"]
      },
      "UpdateTagDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 40
          },
          "color": {
            "type": "string",
            "example": "#16A34A"
          }
        }
      },
      "VisitorTagNamesDto": {
        "type": "object",
        "properties": {
          "tags": {
            "example": ["vip", "newsletter"],
            "maxItems": 10,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["tags"]
      },
      "WidgetConsentRequestDto": {
        "type": "object",
        "properties": {
          "decision": {
            "type": "string",
            "enum": ["accepted", "necessary_only", "opt_out", "gpc", "withdrawn"],
            "description": "`accepted` / `necessary_only` from the consent prompt or `ZebChat.consent()`, `opt_out` from \"Do Not Sell or Share\", `gpc` for the Global Privacy Control signal, `withdrawn` when an earlier acceptance is taken back"
          },
          "source": {
            "type": "string",
            "enum": ["widget", "host_api", "gpc"],
            "description": "`gpc` goes with the `gpc` decision only"
          }
        },
        "required": ["decision", "source"]
      },
      "ConsentLogEntryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cns_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "visitorId": {
            "type": "string",
            "example": "vis_…"
          },
          "conversationId": {
            "type": "string",
            "nullable": true,
            "example": "conv_…"
          },
          "purpose": {
            "type": "string",
            "enum": ["storage", "privacy_policy"],
            "description": "`storage`: storage and tracking; `privacy_policy`: the pre-chat agreement"
          },
          "decision": {
            "type": "string",
            "enum": ["accepted", "necessary_only", "opt_out", "gpc", "withdrawn"]
          },
          "source": {
            "type": "string",
            "enum": ["widget", "host_api", "gpc"]
          },
          "region": {
            "type": "string",
            "enum": ["eu", "us", "other", "unknown"],
            "description": "From the visitor's country"
          },
          "requirement": {
            "type": "string",
            "enum": ["opt_in", "opt_out", "none"],
            "description": "What the policy required there"
          },
          "policyVersion": {
            "type": "string",
            "description": "Hash of the website's consent settings at the time"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "DE",
            "description": "Never the IP"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "websiteId",
          "visitorId",
          "conversationId",
          "purpose",
          "decision",
          "source",
          "region",
          "requirement",
          "policyVersion",
          "country",
          "createdAt"
        ]
      },
      "ConsentLogPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentLogEntryDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "CannedResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cnr_…"
          },
          "shortcut": {
            "type": "string",
            "example": "refund",
            "description": "Typed as /refund"
          },
          "title": {
            "type": "string",
            "example": "Refund policy"
          },
          "body": {
            "type": "string",
            "description": "Text inserted into the composer. Placeholders the apps fill in: {{visitor.name}}, {{visitor.email}}, {{agent.name}}"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "shortcut", "title", "body", "updatedAt"]
      },
      "CreateCannedResponseDto": {
        "type": "object",
        "properties": {
          "shortcut": {
            "type": "string",
            "example": "refund"
          },
          "title": {
            "type": "string",
            "example": "Refund policy",
            "maxLength": 100
          },
          "body": {
            "type": "string",
            "maxLength": 5000
          }
        },
        "required": ["shortcut", "title", "body"]
      },
      "UpdateCannedResponseDto": {
        "type": "object",
        "properties": {
          "shortcut": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "maxLength": 100
          },
          "body": {
            "type": "string",
            "maxLength": 5000
          }
        }
      },
      "AvatarDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ava"
          },
          "url": {
            "type": "string",
            "description": "Public image URL, usable as a profile photo or widget avatar"
          }
        },
        "required": ["id", "url"]
      },
      "UploadedAvatarDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Public image URL, usable as a profile photo or widget avatar"
          }
        },
        "required": ["url"]
      },
      "VisitorRatingDto": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "rating": {
            "type": "number",
            "minimum": 1,
            "maximum": 5
          },
          "comment": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "editableUntil": {
            "type": "string",
            "format": "date-time",
            "description": "The rating can be changed until then (24 h after it was first given)"
          }
        },
        "required": [
          "conversationId",
          "rating",
          "comment",
          "createdAt",
          "updatedAt",
          "editableUntil"
        ]
      },
      "RateConversationDto": {
        "type": "object",
        "properties": {
          "rating": {
            "type": "number",
            "minimum": 1,
            "maximum": 5,
            "example": 5
          },
          "comment": {
            "type": "string",
            "nullable": true,
            "maxLength": 1000,
            "example": "Quick and friendly, thanks!",
            "description": "Omit to keep the current comment; null or \"\" removes it"
          }
        },
        "required": ["rating"]
      },
      "SendTranscriptDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "description": "Where to send it. Omit to use the visitor's saved email; a new one is saved on the visitor (refused for verified visitors)"
          },
          "timeZone": {
            "type": "string",
            "example": "Europe/Berlin",
            "description": "IANA time zone for the message times (unknown zones use the organization's)"
          }
        }
      },
      "TranscriptSentDto": {
        "type": "object",
        "properties": {
          "sentTo": {
            "type": "string",
            "example": "ana@example.com"
          },
          "visitor": {
            "description": "The visitor (the email may be new)",
            "allOf": [
              {
                "$ref": "#/components/schemas/WidgetVisitorDto"
              }
            ]
          }
        },
        "required": ["sentTo", "visitor"]
      },
      "AnalyticsRangeDto": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "example": "2026-09-01"
          },
          "to": {
            "type": "string",
            "example": "2026-09-30"
          },
          "days": {
            "type": "number",
            "example": 30
          },
          "timezone": {
            "type": "string",
            "example": "Europe/Berlin",
            "description": "The organization's IANA time zone: all days are calendar days there"
          }
        },
        "required": ["from", "to", "days", "timezone"]
      },
      "AnalyticsTotalsDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "conversations": {
            "type": "number",
            "description": "Created in the range (spam excluded)"
          },
          "newConversations": {
            "type": "number",
            "description": "Created in the range as the visitor's first conversation"
          },
          "resolved": {
            "type": "number",
            "description": "Resolved or closed in the range"
          },
          "unresolved": {
            "type": "number",
            "description": "Created in the range and still active now (live)"
          },
          "missed": {
            "type": "number",
            "description": "Created in the range and never answered by an agent"
          },
          "averageFirstResponseSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Created → first agent reply, for chats the visitor started (seconds)"
          },
          "averageResolutionSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Created → resolved/closed (seconds)"
          },
          "averageDurationSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Created → last message, for chats that ended (seconds)"
          },
          "visitors": {
            "type": "number",
            "description": "Distinct visitors per day, summed (not team-specific)"
          },
          "chatsPerVisitor": {
            "type": "number",
            "nullable": true,
            "description": "conversations / visitors"
          },
          "agentUtilization": {
            "type": "number",
            "nullable": true,
            "description": "Share of agents' online time with at least one assigned chat, percent"
          },
          "agentOnlineSeconds": {
            "type": "number",
            "description": "Agents' online time (seconds)"
          }
        },
        "required": [
          "ratings",
          "averageRating",
          "csat",
          "conversations",
          "newConversations",
          "resolved",
          "unresolved",
          "missed",
          "averageFirstResponseSeconds",
          "averageResolutionSeconds",
          "averageDurationSeconds",
          "visitors",
          "chatsPerVisitor",
          "agentUtilization",
          "agentOnlineSeconds"
        ]
      },
      "AnalyticsLiveDto": {
        "type": "object",
        "properties": {
          "activeConversations": {
            "type": "number",
            "description": "Active conversations now (new, open, pending, waiting)"
          },
          "queued": {
            "type": "number",
            "description": "Active and unassigned (waiting in the queue)"
          }
        },
        "required": ["activeConversations", "queued"]
      },
      "AnalyticsDayDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "date": {
            "type": "string",
            "example": "2026-09-01"
          },
          "conversations": {
            "type": "number"
          },
          "newConversations": {
            "type": "number"
          },
          "resolved": {
            "type": "number"
          },
          "missed": {
            "type": "number"
          },
          "averageFirstResponseSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Seconds"
          },
          "averageResolutionSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Seconds"
          },
          "visitors": {
            "type": "number"
          }
        },
        "required": [
          "ratings",
          "averageRating",
          "csat",
          "date",
          "conversations",
          "newConversations",
          "resolved",
          "missed",
          "averageFirstResponseSeconds",
          "averageResolutionSeconds",
          "visitors"
        ]
      },
      "AnalyticsOverviewDto": {
        "type": "object",
        "properties": {
          "range": {
            "$ref": "#/components/schemas/AnalyticsRangeDto"
          },
          "totals": {
            "$ref": "#/components/schemas/AnalyticsTotalsDto"
          },
          "live": {
            "$ref": "#/components/schemas/AnalyticsLiveDto"
          },
          "series": {
            "description": "One entry per day, oldest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnalyticsDayDto"
            }
          },
          "refreshedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "When the rollup last ran for a day in the range (data lags up to ~5 min)"
          }
        },
        "required": ["range", "totals", "live", "series", "refreshedAt"]
      },
      "AgentAnalyticsRowDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "example": "agent"
          },
          "chatsHandled": {
            "type": "number",
            "description": "Conversations the agent first replied to in the range"
          },
          "messagesSent": {
            "type": "number",
            "description": "Messages sent (internal notes excluded)"
          },
          "averageResponseSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Waiting visitor → agent reply (seconds)"
          },
          "closedChats": {
            "type": "number",
            "description": "Assigned conversations resolved or closed in the range"
          },
          "averageResolutionSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Created → resolved/closed (seconds)"
          },
          "activeChats": {
            "type": "number",
            "description": "Live: active conversations assigned now"
          },
          "onlineSeconds": {
            "type": "number",
            "description": "App connected with status online or busy (seconds)"
          },
          "utilization": {
            "type": "number",
            "nullable": true,
            "description": "Share of online time with at least one assigned chat, percent"
          }
        },
        "required": [
          "ratings",
          "averageRating",
          "csat",
          "userId",
          "name",
          "role",
          "chatsHandled",
          "messagesSent",
          "averageResponseSeconds",
          "closedChats",
          "averageResolutionSeconds",
          "activeChats",
          "onlineSeconds",
          "utilization"
        ]
      },
      "AgentAnalyticsDto": {
        "type": "object",
        "properties": {
          "range": {
            "$ref": "#/components/schemas/AnalyticsRangeDto"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentAnalyticsRowDto"
            }
          },
          "refreshedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": ["range", "data", "refreshedAt"]
      },
      "FeedbackTotalsDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "comments": {
            "type": "number",
            "description": "Ratings with a comment"
          },
          "distribution": {
            "example": [1, 0, 2, 5, 12],
            "description": "Ratings per star: index 0 = 1 star … index 4 = 5 stars",
            "type": "array",
            "items": {
              "type": "number"
            }
          },
          "conversations": {
            "type": "number",
            "description": "Conversations created in the range (spam excluded)"
          },
          "responseRate": {
            "type": "number",
            "nullable": true,
            "description": "Ratings as a share of those conversations, percent"
          }
        },
        "required": [
          "ratings",
          "averageRating",
          "csat",
          "comments",
          "distribution",
          "conversations",
          "responseRate"
        ]
      },
      "FeedbackDayDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "date": {
            "type": "string",
            "example": "2026-09-30"
          },
          "comments": {
            "type": "number"
          }
        },
        "required": ["ratings", "averageRating", "csat", "date", "comments"]
      },
      "FeedbackGroupDto": {
        "type": "object",
        "properties": {
          "ratings": {
            "type": "number",
            "description": "Ratings given"
          },
          "averageRating": {
            "type": "number",
            "nullable": true,
            "description": "Average stars (1–5, two decimals)"
          },
          "csat": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent (0–100)"
          },
          "id": {
            "type": "string",
            "nullable": true,
            "description": "`usr_…`, `team_…` or `web_…`; null = unassigned / no team"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["ratings", "averageRating", "csat", "id", "name"]
      },
      "AiFeedbackDayDto": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "example": "2026-09-30"
          },
          "up": {
            "type": "number"
          },
          "down": {
            "type": "number"
          }
        },
        "required": ["date", "up", "down"]
      },
      "AiFeedbackSummaryDto": {
        "type": "object",
        "properties": {
          "up": {
            "type": "number"
          },
          "down": {
            "type": "number"
          },
          "satisfaction": {
            "type": "number",
            "nullable": true,
            "description": "Thumbs up as a share of all votes, percent"
          },
          "notes": {
            "type": "number",
            "description": "Votes with a note"
          },
          "series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiFeedbackDayDto"
            }
          }
        },
        "required": ["up", "down", "satisfaction", "notes", "series"]
      },
      "FeedbackReportDto": {
        "type": "object",
        "properties": {
          "range": {
            "$ref": "#/components/schemas/AnalyticsRangeDto"
          },
          "totals": {
            "$ref": "#/components/schemas/FeedbackTotalsDto"
          },
          "series": {
            "description": "Every day of the range, oldest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackDayDto"
            }
          },
          "byAgent": {
            "description": "Most ratings first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackGroupDto"
            }
          },
          "byTeam": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackGroupDto"
            }
          },
          "byWebsite": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackGroupDto"
            }
          },
          "ai": {
            "description": "Agents' thumbs up/down on AI replies (range only; other filters don't apply)",
            "allOf": [
              {
                "$ref": "#/components/schemas/AiFeedbackSummaryDto"
              }
            ]
          }
        },
        "required": ["range", "totals", "series", "byAgent", "byTeam", "byWebsite", "ai"]
      },
      "RefDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "FeedbackVisitorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["id", "name", "email"]
      },
      "FeedbackCommentDto": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "rating": {
            "type": "number",
            "minimum": 1,
            "maximum": 5
          },
          "comment": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the visitor first rated"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "agent": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/RefDto"
              }
            ]
          },
          "team": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/RefDto"
              }
            ]
          },
          "website": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/RefDto"
              }
            ]
          },
          "visitor": {
            "$ref": "#/components/schemas/FeedbackVisitorDto"
          }
        },
        "required": [
          "conversationId",
          "rating",
          "comment",
          "createdAt",
          "updatedAt",
          "agent",
          "team",
          "website",
          "visitor"
        ]
      },
      "FeedbackCommentPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackCommentDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data", "nextCursor"]
      },
      "AiFeedbackItemDto": {
        "type": "object",
        "properties": {
          "messageId": {
            "type": "string",
            "example": "msg_…"
          },
          "conversationId": {
            "type": "string",
            "example": "conv_…"
          },
          "rating": {
            "type": "string",
            "enum": ["up", "down"]
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "userName": {
            "type": "string"
          },
          "excerpt": {
            "type": "string",
            "description": "The first 200 characters of the AI reply"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "messageId",
          "conversationId",
          "rating",
          "note",
          "userId",
          "userName",
          "excerpt",
          "createdAt"
        ]
      },
      "AiFeedbackPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiFeedbackItemDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data", "nextCursor"]
      },
      "HeadlineComparisonDto": {
        "type": "object",
        "properties": {
          "current": {
            "type": "number",
            "nullable": true,
            "description": "This period"
          },
          "previous": {
            "type": "number",
            "nullable": true,
            "description": "The previous period of the same length"
          },
          "changePercent": {
            "type": "number",
            "nullable": true,
            "description": "(current − previous) ÷ previous, percent; null without a previous value"
          }
        },
        "required": ["current", "previous", "changePercent"]
      },
      "AdvancedHeadlineDto": {
        "type": "object",
        "properties": {
          "conversations": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "missed": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "missedRate": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "resolved": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "averageFirstResponseSeconds": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "averageResolutionSeconds": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "averageDurationSeconds": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "csat": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "ratings": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          },
          "visitors": {
            "$ref": "#/components/schemas/HeadlineComparisonDto"
          }
        },
        "required": [
          "conversations",
          "missed",
          "missedRate",
          "resolved",
          "averageFirstResponseSeconds",
          "averageResolutionSeconds",
          "averageDurationSeconds",
          "csat",
          "ratings",
          "visitors"
        ]
      },
      "BreakdownRowDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true,
            "description": "web_…/team_…/usr_…, or the source domain, country code or page; null for none and for the \"other\" row"
          },
          "label": {
            "type": "string"
          },
          "other": {
            "type": "boolean",
            "description": "Sum of everything past the top N"
          },
          "conversations": {
            "type": "number"
          },
          "missed": {
            "type": "number"
          },
          "missedRate": {
            "type": "number",
            "nullable": true,
            "description": "missed ÷ conversations, percent"
          },
          "averageFirstResponseSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Seconds"
          },
          "averageDurationSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Created → last message of ended chats (seconds)"
          },
          "ratings": {
            "type": "number"
          },
          "goodRate": {
            "type": "number",
            "nullable": true,
            "description": "Share of 4–5 star ratings, percent"
          },
          "badRate": {
            "type": "number",
            "nullable": true,
            "description": "Share of 1–2 star ratings, percent"
          }
        },
        "required": [
          "key",
          "label",
          "other",
          "conversations",
          "missed",
          "missedRate",
          "averageFirstResponseSeconds",
          "averageDurationSeconds",
          "ratings",
          "goodRate",
          "badRate"
        ]
      },
      "AdvancedBreakdownsDto": {
        "type": "object",
        "properties": {
          "website": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          },
          "team": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          },
          "agent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          },
          "source": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          },
          "country": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          },
          "landingPage": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownRowDto"
            }
          }
        },
        "required": ["website", "team", "agent", "source", "country", "landingPage"]
      },
      "HeatmapCellDto": {
        "type": "object",
        "properties": {
          "weekday": {
            "type": "number",
            "minimum": 1,
            "maximum": 7,
            "description": "ISO weekday, 1 = Monday"
          },
          "hour": {
            "type": "number",
            "minimum": 0,
            "maximum": 23
          },
          "conversations": {
            "type": "number"
          },
          "visits": {
            "type": "number"
          },
          "pageviews": {
            "type": "number"
          }
        },
        "required": ["weekday", "hour", "conversations", "visits", "pageviews"]
      },
      "ResponseTimeBucketDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "enum": ["under30s", "30sTo1m", "1mTo2m", "2mTo5m", "over5m"]
          },
          "label": {
            "type": "string",
            "example": "< 30s"
          },
          "conversations": {
            "type": "number"
          },
          "share": {
            "type": "number",
            "nullable": true,
            "description": "Share of answered conversations, percent"
          }
        },
        "required": ["key", "label", "conversations", "share"]
      },
      "ResponseTimeDistributionDto": {
        "type": "object",
        "properties": {
          "answered": {
            "type": "number"
          },
          "missed": {
            "type": "number"
          },
          "medianSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Seconds"
          },
          "p90Seconds": {
            "type": "number",
            "nullable": true,
            "description": "Seconds"
          },
          "buckets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResponseTimeBucketDto"
            }
          }
        },
        "required": ["answered", "missed", "medianSeconds", "p90Seconds", "buckets"]
      },
      "MissedTrendDayDto": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "example": "2026-09-01"
          },
          "conversations": {
            "type": "number"
          },
          "missed": {
            "type": "number"
          },
          "missedRate": {
            "type": "number",
            "nullable": true,
            "description": "Percent"
          }
        },
        "required": ["date", "conversations", "missed", "missedRate"]
      },
      "AdvancedAnalyticsDto": {
        "type": "object",
        "properties": {
          "range": {
            "$ref": "#/components/schemas/AnalyticsRangeDto"
          },
          "previousRange": {
            "$ref": "#/components/schemas/AnalyticsRangeDto"
          },
          "headline": {
            "$ref": "#/components/schemas/AdvancedHeadlineDto"
          },
          "breakdowns": {
            "$ref": "#/components/schemas/AdvancedBreakdownsDto"
          },
          "heatmap": {
            "description": "168 cells, Monday 00:00 first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HeatmapCellDto"
            }
          },
          "responseTimes": {
            "$ref": "#/components/schemas/ResponseTimeDistributionDto"
          },
          "missedTrend": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MissedTrendDayDto"
            }
          },
          "refreshedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "range",
          "previousRange",
          "headline",
          "breakdowns",
          "heatmap",
          "responseTimes",
          "missedTrend",
          "refreshedAt"
        ]
      },
      "ApiKeyCreatorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "usr_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["id", "name"]
      },
      "ApiKeyDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "key_…"
          },
          "name": {
            "type": "string",
            "example": "Zapier"
          },
          "prefix": {
            "type": "string",
            "example": "zck_Ab3dEf9h",
            "description": "The public start of the key, to recognize it (the secret part is never shown again)"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "org:read",
                "members:read",
                "websites:read",
                "visitors:read",
                "contacts:read",
                "contacts:manage",
                "conversations:read",
                "conversations:reply",
                "conversations:manage",
                "teams:manage",
                "canned:manage",
                "tags:manage",
                "reports:read",
                "knowledge:read"
              ]
            }
          },
          "rateLimitPerMinute": {
            "type": "number",
            "example": 120
          },
          "status": {
            "type": "string",
            "enum": ["active", "expired", "revoked"]
          },
          "createdBy": {
            "description": "The key acts as this member",
            "allOf": [
              {
                "$ref": "#/components/schemas/ApiKeyCreatorDto"
              }
            ]
          },
          "expiresAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Updated at most once a minute"
          },
          "revokedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "rateLimitPerMinute",
          "status",
          "createdBy",
          "expiresAt",
          "lastUsedAt",
          "revokedAt",
          "createdAt"
        ]
      },
      "CreateApiKeyDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Zapier",
            "maxLength": 100
          },
          "scopes": {
            "type": "array",
            "description": "What the key may do. It never gets more than its creator's role allows, now or later",
            "items": {
              "type": "string",
              "enum": [
                "org:read",
                "members:read",
                "websites:read",
                "visitors:read",
                "contacts:read",
                "contacts:manage",
                "conversations:read",
                "conversations:reply",
                "conversations:manage",
                "teams:manage",
                "canned:manage",
                "tags:manage",
                "reports:read",
                "knowledge:read"
              ]
            }
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string",
            "description": "When the key stops working (omit for no expiry)"
          },
          "rateLimitPerMinute": {
            "type": "number",
            "minimum": 1,
            "maximum": 1200,
            "default": 120,
            "description": "Requests per minute"
          }
        },
        "required": ["name", "scopes"]
      },
      "CreatedApiKeyDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "key_…"
          },
          "name": {
            "type": "string",
            "example": "Zapier"
          },
          "prefix": {
            "type": "string",
            "example": "zck_Ab3dEf9h",
            "description": "The public start of the key, to recognize it (the secret part is never shown again)"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "org:read",
                "members:read",
                "websites:read",
                "visitors:read",
                "contacts:read",
                "contacts:manage",
                "conversations:read",
                "conversations:reply",
                "conversations:manage",
                "teams:manage",
                "canned:manage",
                "tags:manage",
                "reports:read",
                "knowledge:read"
              ]
            }
          },
          "rateLimitPerMinute": {
            "type": "number",
            "example": 120
          },
          "status": {
            "type": "string",
            "enum": ["active", "expired", "revoked"]
          },
          "createdBy": {
            "description": "The key acts as this member",
            "allOf": [
              {
                "$ref": "#/components/schemas/ApiKeyCreatorDto"
              }
            ]
          },
          "expiresAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Updated at most once a minute"
          },
          "revokedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "key": {
            "type": "string",
            "example": "zck_Ab3dEf9h_…",
            "description": "The full key. Shown only in this response: store it now"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "rateLimitPerMinute",
          "status",
          "createdBy",
          "expiresAt",
          "lastUsedAt",
          "revokedAt",
          "createdAt",
          "key"
        ]
      },
      "IntegrationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "int_…"
          },
          "provider": {
            "type": "string",
            "enum": [
              "slack",
              "shopify",
              "hubspot",
              "zoho",
              "salesforce",
              "zapier",
              "make",
              "bigcommerce"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "label": {
            "type": "string",
            "example": "#support",
            "description": "A name you gave this connection"
          },
          "detail": {
            "type": "string",
            "example": "hooks.slack.com",
            "description": "Shop domain, hook host, or CRM host. Not the secret itself."
          },
          "websiteId": {
            "type": "string",
            "example": "web_…",
            "description": "Shopify only: the ZebChat website whose widget is installed"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "provider",
          "enabled",
          "events",
          "label",
          "detail",
          "websiteId",
          "createdAt",
          "updatedAt"
        ]
      },
      "ConnectIntegrationDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "slack",
              "shopify",
              "hubspot",
              "zoho",
              "salesforce",
              "zapier",
              "make",
              "bigcommerce"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "label": {
            "type": "string",
            "example": "#support"
          },
          "webhookUrl": {
            "type": "string",
            "description": "Slack, Zapier or Make hook URL"
          },
          "token": {
            "type": "string",
            "description": "HubSpot, Zoho, Salesforce or Shopify Admin API token"
          },
          "apiSecret": {
            "type": "string",
            "description": "Shopify API secret, used to verify inbound webhooks"
          },
          "shop": {
            "type": "string",
            "example": "my-shop.myshopify.com"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "apiDomain": {
            "type": "string",
            "example": "https://www.zohoapis.eu"
          },
          "instanceUrl": {
            "type": "string",
            "example": "https://acme.my.salesforce.com"
          }
        },
        "required": ["provider"]
      },
      "UpdateIntegrationDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "label": {
            "type": "string"
          }
        }
      },
      "WebhookEndpointDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "whk_…"
          },
          "url": {
            "type": "string",
            "example": "https://hooks.example.com/zebchat"
          },
          "description": {
            "type": "string",
            "example": "CRM sync"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "includeInternal": {
            "type": "boolean",
            "description": "`message.created` also fires for internal notes"
          },
          "enabled": {
            "type": "boolean"
          },
          "disabledReason": {
            "type": "string",
            "nullable": true,
            "enum": ["failing"],
            "description": "`failing` when ZebChat switched the endpoint off after too many failures"
          },
          "disabledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "consecutiveFailures": {
            "type": "number",
            "description": "Failed deliveries since the last success"
          },
          "lastSuccessAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastFailureAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "description",
          "events",
          "includeInternal",
          "enabled",
          "disabledReason",
          "disabledAt",
          "consecutiveFailures",
          "lastSuccessAt",
          "lastFailureAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateWebhookEndpointDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "example": "https://hooks.example.com/zebchat",
            "maxLength": 2048,
            "description": "https:// on a public address"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "description": {
            "type": "string",
            "maxLength": 200,
            "default": ""
          },
          "includeInternal": {
            "type": "boolean",
            "default": false
          },
          "enabled": {
            "type": "boolean",
            "default": true
          }
        },
        "required": ["url", "events"]
      },
      "CreatedWebhookEndpointDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "whk_…"
          },
          "url": {
            "type": "string",
            "example": "https://hooks.example.com/zebchat"
          },
          "description": {
            "type": "string",
            "example": "CRM sync"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "includeInternal": {
            "type": "boolean",
            "description": "`message.created` also fires for internal notes"
          },
          "enabled": {
            "type": "boolean"
          },
          "disabledReason": {
            "type": "string",
            "nullable": true,
            "enum": ["failing"],
            "description": "`failing` when ZebChat switched the endpoint off after too many failures"
          },
          "disabledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "consecutiveFailures": {
            "type": "number",
            "description": "Failed deliveries since the last success"
          },
          "lastSuccessAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastFailureAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "example": "whsec_…",
            "description": "Signing secret. Shown only here and when rotated: store it now"
          }
        },
        "required": [
          "id",
          "url",
          "description",
          "events",
          "includeInternal",
          "enabled",
          "disabledReason",
          "disabledAt",
          "consecutiveFailures",
          "lastSuccessAt",
          "lastFailureAt",
          "createdAt",
          "updatedAt",
          "secret"
        ]
      },
      "UpdateWebhookEndpointDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "conversation.created",
                "conversation.assigned",
                "conversation.resolved",
                "conversation.closed",
                "conversation.reopened",
                "conversation.rated",
                "message.created",
                "offline_message.created",
                "visitor.identified",
                "contact.created",
                "contact.updated"
              ]
            }
          },
          "description": {
            "type": "string",
            "maxLength": 200
          },
          "includeInternal": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean",
            "description": "Turning an endpoint back on resets its failure count"
          }
        }
      },
      "WebhookSecretDto": {
        "type": "object",
        "properties": {
          "secret": {
            "type": "string",
            "example": "whsec_…",
            "description": "The new signing secret (the old one stops now)"
          }
        },
        "required": ["secret"]
      },
      "WebhookDeliveryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "whd_…",
            "description": "This attempt (sent as ZebChat-Delivery)"
          },
          "eventId": {
            "type": "string",
            "example": "evt_…",
            "description": "The event: the same on retries and replays"
          },
          "eventType": {
            "type": "string",
            "example": "message.created"
          },
          "attempt": {
            "type": "number",
            "description": "1 for the first try and replays, 2… for automatic retries"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "succeeded", "failed"]
          },
          "responseStatus": {
            "type": "number",
            "nullable": true
          },
          "durationMs": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "nextAttemptAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Pending: when it will be tried. Failed: when the retry is due (null = no retry)"
          },
          "replayOf": {
            "type": "string",
            "nullable": true,
            "example": "whd_…"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "eventId",
          "eventType",
          "attempt",
          "status",
          "responseStatus",
          "durationMs",
          "error",
          "nextAttemptAt",
          "replayOf",
          "createdAt",
          "completedAt"
        ]
      },
      "WebhookDeliveryPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Newest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data"]
      },
      "WebhookDeliveryDetailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "whd_…",
            "description": "This attempt (sent as ZebChat-Delivery)"
          },
          "eventId": {
            "type": "string",
            "example": "evt_…",
            "description": "The event: the same on retries and replays"
          },
          "eventType": {
            "type": "string",
            "example": "message.created"
          },
          "attempt": {
            "type": "number",
            "description": "1 for the first try and replays, 2… for automatic retries"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "succeeded", "failed"]
          },
          "responseStatus": {
            "type": "number",
            "nullable": true
          },
          "durationMs": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "nextAttemptAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Pending: when it will be tried. Failed: when the retry is due (null = no retry)"
          },
          "replayOf": {
            "type": "string",
            "nullable": true,
            "example": "whd_…"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "payload": {
            "type": "object",
            "additionalProperties": true,
            "description": "The event body that was sent: {id, type, createdAt, organizationId, data}"
          },
          "responseBody": {
            "type": "string",
            "nullable": true,
            "description": "First 2 KB of the response"
          }
        },
        "required": [
          "id",
          "eventId",
          "eventType",
          "attempt",
          "status",
          "responseStatus",
          "durationMs",
          "error",
          "nextAttemptAt",
          "replayOf",
          "createdAt",
          "completedAt",
          "payload",
          "responseBody"
        ]
      },
      "PlatformSettingsResponseDto": {
        "type": "object",
        "properties": {
          "groups": {
            "type": "object",
            "description": "One list of fields per group (smtp, branding, stripe, paypal, push, turnstile, maps, general). Plain fields: {key, field, secret: false, value, source, updatedAt}. Secrets: {key, field, secret: true, configured, last4, projectId, source, updatedAt}; their values are never returned. source: database | environment | default",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          },
          "environment": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Environment-only values: {name, configured, description} (never the value)"
          },
          "appUrl": {
            "type": "string",
            "description": "APP_PUBLIC_URL (environment only)"
          },
          "encryptionConfigured": {
            "type": "boolean",
            "description": "SETTINGS_ENCRYPTION_KEY is set: secrets can be saved"
          }
        },
        "required": ["groups", "environment", "appUrl", "encryptionConfigured"]
      },
      "EncryptionKeyStatusDto": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean",
            "description": "SETTINGS_ENCRYPTION_KEY is set"
          },
          "currentKeyId": {
            "type": "string",
            "nullable": true,
            "description": "First 8 hex of the current key’s SHA-256 (not secret)"
          },
          "previousKeys": {
            "type": "number",
            "description": "Keys listed in SETTINGS_ENCRYPTION_PREVIOUS_KEYS"
          },
          "stores": {
            "type": "object",
            "description": "Counts per store (platformSettings, twoFactor, aiCredentials, aiActions, integrations): {current, stale, unreadable}",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "current": {
                  "type": "integer"
                },
                "stale": {
                  "type": "integer"
                },
                "unreadable": {
                  "type": "integer"
                }
              }
            }
          },
          "stale": {
            "type": "number",
            "description": "Total stale values: the previous keys can go once this is 0"
          },
          "unreadable": {
            "type": "number",
            "description": "Total values no configured key can read"
          }
        },
        "required": ["configured", "currentKeyId", "previousKeys", "stores", "stale", "unreadable"]
      },
      "ResealSecretsResultDto": {
        "type": "object",
        "properties": {
          "resealed": {
            "type": "object",
            "description": "Values re-encrypted per store (platformSettings, twoFactor, aiCredentials, aiActions, integrations)",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "failed": {
            "type": "number",
            "description": "Values that could not be decrypted and were left as they are"
          },
          "status": {
            "$ref": "#/components/schemas/EncryptionKeyStatusDto"
          }
        },
        "required": ["resealed", "failed", "status"]
      },
      "SettingsTestResultDto": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        },
        "required": ["ok", "message"]
      },
      "EmailPreviewDto": {
        "type": "object",
        "properties": {
          "template": {
            "type": "string",
            "enum": [
              "chat-alert",
              "verify-email",
              "reset-password",
              "invitation",
              "chat-transcript",
              "webhook-disabled",
              "ai-key-failed",
              "organization-suspended",
              "organization-unsuspended",
              "two-factor-enabled",
              "two-factor-disabled",
              "two-factor-reset",
              "two-factor-recovery-code-used",
              "account-deleted"
            ]
          },
          "subject": {
            "type": "string"
          },
          "html": {
            "type": "string",
            "description": "The complete HTML document with the sample content (show it in a sandboxed iframe)"
          },
          "text": {
            "type": "string",
            "description": "The plain-text part"
          }
        },
        "required": ["template", "subject", "html", "text"]
      },
      "PlanPricesDto": {
        "type": "object",
        "properties": {
          "month": {
            "type": "number",
            "description": "Cents per month"
          },
          "year": {
            "type": "number",
            "description": "Cents per year"
          }
        },
        "required": ["month", "year"]
      },
      "PlanLimitsDto": {
        "type": "object",
        "properties": {
          "agents": {
            "type": "number",
            "nullable": true,
            "description": "Agent seats (null = unlimited)"
          },
          "websites": {
            "type": "number",
            "nullable": true
          },
          "concurrentChats": {
            "type": "number",
            "nullable": true,
            "description": "Simultaneous live chats people answer; more visitors wait in the queue"
          },
          "storageBytes": {
            "type": "number",
            "nullable": true,
            "description": "Bytes"
          },
          "maxRetentionDays": {
            "type": "number",
            "nullable": true,
            "description": "Longest an organization may keep ended conversations, in days (null = unlimited); caps its own retention setting. Any whole number from 1; Admin → Plans offers the retention presets (30, 90, 180, 365, 730, 1095, 1825, 2555 days)"
          }
        },
        "required": ["agents", "websites", "concurrentChats", "storageBytes", "maxRetentionDays"]
      },
      "PlanFeaturesDto": {
        "type": "object",
        "properties": {
          "removeBranding": {
            "type": "boolean"
          },
          "advancedAnalytics": {
            "type": "boolean"
          },
          "automations": {
            "type": "boolean"
          },
          "ai": {
            "type": "boolean"
          },
          "knowledgeBase": {
            "type": "boolean"
          },
          "api": {
            "type": "boolean"
          },
          "identityVerification": {
            "type": "boolean"
          },
          "prioritySupport": {
            "type": "boolean"
          }
        },
        "required": [
          "removeBranding",
          "advancedAnalytics",
          "automations",
          "ai",
          "knowledgeBase",
          "api",
          "identityVerification",
          "prioritySupport"
        ]
      },
      "AdminPlanDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"]
          },
          "name": {
            "type": "string"
          },
          "tagline": {
            "type": "string"
          },
          "prices": {
            "$ref": "#/components/schemas/PlanPricesDto"
          },
          "currency": {
            "type": "string"
          },
          "customPricing": {
            "type": "boolean"
          },
          "limits": {
            "$ref": "#/components/schemas/PlanLimitsDto"
          },
          "features": {
            "$ref": "#/components/schemas/PlanFeaturesDto"
          },
          "highlights": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visible": {
            "type": "boolean"
          },
          "active": {
            "type": "boolean"
          },
          "sortOrder": {
            "type": "number"
          },
          "organizations": {
            "type": "number",
            "description": "Organizations whose plan in force this is"
          },
          "subscribers": {
            "type": "number",
            "description": "Live subscriptions (or still in their paid period)"
          },
          "updatedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "code",
          "name",
          "tagline",
          "prices",
          "currency",
          "customPricing",
          "limits",
          "features",
          "highlights",
          "visible",
          "active",
          "sortOrder",
          "organizations",
          "subscribers",
          "updatedAt"
        ]
      },
      "AdminPlanListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminPlanDto"
            }
          },
          "missing": {
            "type": "array",
            "description": "Plan codes without a row (deleted); PUT brings one back",
            "items": {
              "type": "string",
              "enum": ["free", "starter", "business", "pro", "enterprise"]
            }
          }
        },
        "required": ["data", "missing"]
      },
      "PlanImpactDto": {
        "type": "object",
        "properties": {
          "organizations": {
            "type": "number",
            "description": "Organizations on the plan without their own limits"
          },
          "agents": {
            "type": "number",
            "description": "Of those, how many use more agent seats than proposed"
          },
          "websites": {
            "type": "number"
          },
          "concurrentChats": {
            "type": "number",
            "description": "Of those, how many answer more live chats right now"
          },
          "storageBytes": {
            "type": "number"
          },
          "maxRetentionDays": {
            "type": "number",
            "description": "Of those, how many keep conversations longer than the proposed cap (or forever)"
          }
        },
        "required": [
          "organizations",
          "agents",
          "websites",
          "concurrentChats",
          "storageBytes",
          "maxRetentionDays"
        ]
      },
      "UpdatePlanDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 60
          },
          "tagline": {
            "type": "string",
            "maxLength": 200
          },
          "prices": {
            "$ref": "#/components/schemas/PlanPricesDto"
          },
          "currency": {
            "type": "string",
            "example": "usd"
          },
          "customPricing": {
            "type": "boolean",
            "description": "No list price or checkout: \"Contact sales\" (Enterprise)"
          },
          "limits": {
            "$ref": "#/components/schemas/PlanLimitsDto"
          },
          "features": {
            "$ref": "#/components/schemas/PlanFeaturesDto"
          },
          "highlights": {
            "maxItems": 12,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visible": {
            "type": "boolean",
            "description": "Listed on pricing pages"
          },
          "active": {
            "type": "boolean",
            "description": "Inactive: hidden and no new subscriptions; existing subscribers keep it"
          },
          "sortOrder": {
            "type": "number"
          }
        },
        "required": [
          "name",
          "tagline",
          "prices",
          "currency",
          "customPricing",
          "limits",
          "features",
          "highlights",
          "visible",
          "active",
          "sortOrder"
        ]
      },
      "CustomLimitsDto": {
        "type": "object",
        "properties": {
          "limits": {
            "$ref": "#/components/schemas/PlanLimitsDto"
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["limits", "note", "updatedAt"]
      },
      "OrganizationLimitsDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string",
            "example": "org_…"
          },
          "plan": {
            "type": "string",
            "enum": ["free", "starter", "business", "pro", "enterprise"],
            "description": "The plan in force"
          },
          "custom": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomLimitsDto"
              }
            ]
          },
          "effective": {
            "description": "The limits that apply now",
            "allOf": [
              {
                "$ref": "#/components/schemas/PlanLimitsDto"
              }
            ]
          },
          "activeChats": {
            "type": "number",
            "description": "Live chats people are answering now (see concurrentChats)"
          }
        },
        "required": ["organizationId", "plan", "custom", "effective", "activeChats"]
      },
      "SetOrganizationLimitsDto": {
        "type": "object",
        "properties": {
          "limits": {
            "description": "Replaces all four plan limits (null = unlimited)",
            "allOf": [
              {
                "$ref": "#/components/schemas/PlanLimitsDto"
              }
            ]
          },
          "note": {
            "type": "string",
            "maxLength": 500,
            "description": "Why (contract, ticket)"
          }
        },
        "required": ["limits", "note"]
      },
      "ConnectionsDto": {
        "type": "object",
        "properties": {
          "used": {
            "type": "number"
          },
          "max": {
            "type": "number"
          }
        },
        "required": ["used", "max"]
      },
      "TableSizeDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "totalBytes": {
            "type": "number"
          },
          "rows": {
            "type": "number",
            "description": "Estimated rows (planner statistics)"
          },
          "deadRows": {
            "type": "number"
          }
        },
        "required": ["name", "totalBytes", "rows", "deadRows"]
      },
      "PostgresHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "latencyMs": {
            "type": "number",
            "nullable": true
          },
          "version": {
            "type": "string",
            "nullable": true
          },
          "connections": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ConnectionsDto"
              }
            ]
          },
          "databaseBytes": {
            "type": "number",
            "nullable": true
          },
          "largestTables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TableSizeDto"
            }
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "status",
          "latencyMs",
          "version",
          "connections",
          "databaseBytes",
          "largestTables",
          "error"
        ]
      },
      "RedisHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "latencyMs": {
            "type": "number",
            "nullable": true
          },
          "version": {
            "type": "string",
            "nullable": true
          },
          "usedMemoryBytes": {
            "type": "number",
            "nullable": true
          },
          "maxMemoryBytes": {
            "type": "number",
            "nullable": true
          },
          "keys": {
            "type": "number",
            "nullable": true
          },
          "connectedClients": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "status",
          "latencyMs",
          "version",
          "usedMemoryBytes",
          "maxMemoryBytes",
          "keys",
          "connectedClients",
          "error"
        ]
      },
      "StorageHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "driver": {
            "type": "string",
            "enum": ["local", "s3"]
          },
          "latencyMs": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["status", "driver", "latencyMs", "error"]
      },
      "SmtpHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "latencyMs": {
            "type": "number",
            "nullable": true
          },
          "checkedAt": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["status", "latencyMs", "checkedAt", "error"]
      },
      "CurrentApiDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "uptimeSeconds": {
            "type": "number"
          },
          "environment": {
            "type": "string"
          }
        },
        "required": ["id", "version", "uptimeSeconds", "environment"]
      },
      "SocketCountsDto": {
        "type": "object",
        "properties": {
          "agent": {
            "type": "number"
          },
          "visitor": {
            "type": "number"
          }
        },
        "required": ["agent", "visitor"]
      },
      "ProbeDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["up", "down"]
          },
          "latencyMs": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "checkedAt": {
            "type": "string"
          }
        },
        "required": ["status", "latencyMs", "error", "checkedAt"]
      },
      "InstanceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "hostname": {
            "type": "string"
          },
          "pid": {
            "type": "number"
          },
          "version": {
            "type": "string"
          },
          "startedAt": {
            "type": "string"
          },
          "lastSeenAt": {
            "type": "string"
          },
          "uptimeSeconds": {
            "type": "number"
          },
          "queues": {
            "nullable": true,
            "description": "Queues it consumes",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sockets": {
            "nullable": true,
            "description": "API: open sockets",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SocketCountsDto"
              }
            ]
          },
          "current": {
            "type": "boolean",
            "description": "API: the instance answering this request"
          },
          "smtp": {
            "nullable": true,
            "description": "Worker: SMTP check",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/ProbeDto"
              }
            ]
          }
        },
        "required": [
          "id",
          "hostname",
          "pid",
          "version",
          "startedAt",
          "lastSeenAt",
          "uptimeSeconds",
          "queues",
          "sockets",
          "current",
          "smtp"
        ]
      },
      "ApiHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "current": {
            "$ref": "#/components/schemas/CurrentApiDto"
          },
          "instances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceDto"
            }
          }
        },
        "required": ["status", "current", "instances"]
      },
      "WorkerHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "instances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstanceDto"
            }
          },
          "missingQueues": {
            "description": "Queues no running worker or API instance consumes",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["status", "instances", "missingQueues"]
      },
      "RealtimeHealthDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"]
          },
          "sockets": {
            "$ref": "#/components/schemas/SocketCountsDto"
          },
          "onlineAgents": {
            "type": "number"
          },
          "onlineVisitors": {
            "type": "number"
          },
          "organizationsWithAgents": {
            "type": "number"
          },
          "approximate": {
            "type": "boolean",
            "description": "The presence scan stopped at its budget"
          }
        },
        "required": [
          "status",
          "sockets",
          "onlineAgents",
          "onlineVisitors",
          "organizationsWithAgents",
          "approximate"
        ]
      },
      "SystemHealthDto": {
        "type": "object",
        "properties": {
          "generatedAt": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["ok", "warn", "down"],
            "description": "The worst card"
          },
          "postgres": {
            "$ref": "#/components/schemas/PostgresHealthDto"
          },
          "redis": {
            "$ref": "#/components/schemas/RedisHealthDto"
          },
          "storage": {
            "$ref": "#/components/schemas/StorageHealthDto"
          },
          "smtp": {
            "$ref": "#/components/schemas/SmtpHealthDto"
          },
          "api": {
            "$ref": "#/components/schemas/ApiHealthDto"
          },
          "workers": {
            "$ref": "#/components/schemas/WorkerHealthDto"
          },
          "realtime": {
            "$ref": "#/components/schemas/RealtimeHealthDto"
          }
        },
        "required": [
          "generatedAt",
          "status",
          "postgres",
          "redis",
          "storage",
          "smtp",
          "api",
          "workers",
          "realtime"
        ]
      },
      "QueueListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueueSummaryDto"
            }
          }
        },
        "required": ["data"]
      },
      "FailedJobDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "error": {
            "type": "string",
            "description": "Redacted"
          },
          "attemptsMade": {
            "type": "number"
          },
          "maxAttempts": {
            "type": "number"
          },
          "createdAt": {
            "type": "string"
          },
          "failedAt": {
            "type": "string",
            "nullable": true
          },
          "stack": {
            "description": "First lines of the last stack trace (redacted)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "payload": {
            "type": "object",
            "description": "Redacted payload preview: secret keys replaced, emails masked, tokens removed, truncated"
          }
        },
        "required": [
          "id",
          "name",
          "error",
          "attemptsMade",
          "maxAttempts",
          "createdAt",
          "failedAt",
          "stack",
          "payload"
        ]
      },
      "FailedJobPageDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FailedJobDto"
            }
          }
        },
        "required": ["total", "data"]
      },
      "QueueActionResultDto": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "count": {
            "type": "number",
            "description": "Jobs affected"
          }
        },
        "required": ["ok", "count"]
      },
      "DeadLetterEntryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "queue": {
            "type": "string",
            "description": "The original queue"
          },
          "name": {
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "attempts": {
            "type": "number"
          },
          "failedAt": {
            "type": "string"
          },
          "payload": {
            "type": "object",
            "description": "Redacted payload preview"
          }
        },
        "required": ["id", "queue", "name", "error", "attempts", "failedAt", "payload"]
      },
      "DeadLetterPageDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeadLetterEntryDto"
            }
          }
        },
        "required": ["total", "data"]
      },
      "EmailDayDto": {
        "type": "object",
        "properties": {
          "sent": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "retrying": {
            "type": "number"
          }
        },
        "required": ["sent", "failed", "retrying"]
      },
      "EmailRecordDto": {
        "type": "object",
        "properties": {
          "at": {
            "type": "string"
          },
          "jobId": {
            "type": "string",
            "nullable": true
          },
          "template": {
            "type": "string"
          },
          "to": {
            "type": "string",
            "description": "Masked (`ja***@example.com`)"
          },
          "status": {
            "type": "string",
            "enum": ["sent", "failed", "retrying"]
          },
          "attempts": {
            "type": "number"
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["at", "jobId", "template", "to", "status", "attempts", "error"]
      },
      "EmailDeliveryPageDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "last24h": {
            "$ref": "#/components/schemas/EmailDayDto"
          },
          "templates": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailRecordDto"
            }
          }
        },
        "required": ["total", "last24h", "templates", "data"]
      },
      "PushDayDto": {
        "type": "object",
        "properties": {
          "jobs": {
            "type": "number"
          },
          "sent": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "invalidRemoved": {
            "type": "number"
          },
          "failedJobs": {
            "type": "number"
          }
        },
        "required": ["jobs", "sent", "failed", "invalidRemoved", "failedJobs"]
      },
      "PushRecordDto": {
        "type": "object",
        "properties": {
          "at": {
            "type": "string"
          },
          "jobId": {
            "type": "string",
            "nullable": true
          },
          "event": {
            "type": "string"
          },
          "targets": {
            "type": "number"
          },
          "sent": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "invalid": {
            "type": "number",
            "description": "Devices rejected for good (removed by the API)"
          },
          "status": {
            "type": "string",
            "enum": ["sent", "failed", "retrying", "skipped"]
          },
          "attempts": {
            "type": "number"
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "at",
          "jobId",
          "event",
          "targets",
          "sent",
          "failed",
          "invalid",
          "status",
          "attempts",
          "error"
        ]
      },
      "PushDeliveryPageDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "last24h": {
            "$ref": "#/components/schemas/PushDayDto"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PushRecordDto"
            }
          }
        },
        "required": ["total", "last24h", "data"]
      },
      "WebhookStatDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "deliveries": {
            "type": "number"
          },
          "organizations": {
            "type": "number"
          }
        },
        "required": ["status", "deliveries", "organizations"]
      },
      "OrganizationRefDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "WebhookFailureDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationRefDto"
          },
          "endpointHost": {
            "type": "string",
            "description": "Host only, never the full URL"
          },
          "endpointEnabled": {
            "type": "boolean"
          },
          "event": {
            "type": "string"
          },
          "attempt": {
            "type": "number"
          },
          "statusCode": {
            "type": "number",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "organization",
          "endpointHost",
          "endpointEnabled",
          "event",
          "attempt",
          "statusCode",
          "error",
          "at"
        ]
      },
      "WebhookFailurePageDto": {
        "type": "object",
        "properties": {
          "hours": {
            "type": "number"
          },
          "stats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookStatDto"
            }
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookFailureDto"
            }
          }
        },
        "required": ["hours", "stats", "data"]
      },
      "SentryLinkDto": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["configured", "url"]
      },
      "RecentErrorDto": {
        "type": "object",
        "properties": {
          "at": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "route": {
            "type": "string",
            "description": "Route pattern, never the raw URL"
          },
          "status": {
            "type": "number"
          },
          "name": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Redacted, ≤ 300 characters"
          },
          "requestId": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string"
          }
        },
        "required": ["at", "method", "route", "status", "name", "message", "requestId", "instance"]
      },
      "RecentErrorPageDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "sentry": {
            "$ref": "#/components/schemas/SentryLinkDto"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecentErrorDto"
            }
          }
        },
        "required": ["total", "sentry", "data"]
      },
      "MetricsPointDto": {
        "type": "object",
        "properties": {
          "minute": {
            "type": "string"
          },
          "requests": {
            "type": "number"
          },
          "errors": {
            "type": "number"
          },
          "p95Ms": {
            "type": "number",
            "nullable": true
          }
        },
        "required": ["minute", "requests", "errors", "p95Ms"]
      },
      "MetricsPanelDto": {
        "type": "object",
        "properties": {
          "minutes": {
            "type": "number"
          },
          "requests": {
            "type": "number"
          },
          "errors": {
            "type": "number"
          },
          "errorRate": {
            "type": "number",
            "description": "5xx share, percent"
          },
          "requestsPerMinute": {
            "type": "number"
          },
          "p95Ms": {
            "type": "number",
            "nullable": true
          },
          "points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricsPointDto"
            }
          }
        },
        "required": [
          "minutes",
          "requests",
          "errors",
          "errorRate",
          "requestsPerMinute",
          "p95Ms",
          "points"
        ]
      },
      "ActiveAnnouncementDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ann_0199…"
          },
          "kind": {
            "type": "string",
            "enum": ["general", "maintenance"]
          },
          "severity": {
            "type": "string",
            "enum": ["info", "warning", "critical"]
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string",
            "description": "Plain text; clients link http(s) URLs. Never HTML"
          },
          "maintenanceAt": {
            "type": "string",
            "nullable": true
          },
          "startsAt": {
            "type": "string"
          },
          "endsAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "description": "Dismissals are remembered per `id:updatedAt`"
          }
        },
        "required": [
          "id",
          "kind",
          "severity",
          "title",
          "body",
          "maintenanceAt",
          "startsAt",
          "endsAt",
          "updatedAt"
        ]
      },
      "ActiveAnnouncementListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActiveAnnouncementDto"
            }
          }
        },
        "required": ["data"]
      },
      "AnnouncementAuthorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string"
          }
        },
        "required": ["id", "email"]
      },
      "AdminAnnouncementDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ann_0199…"
          },
          "kind": {
            "type": "string",
            "enum": ["general", "maintenance"]
          },
          "severity": {
            "type": "string",
            "enum": ["info", "warning", "critical"]
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string",
            "description": "Plain text; clients link http(s) URLs. Never HTML"
          },
          "maintenanceAt": {
            "type": "string",
            "nullable": true
          },
          "startsAt": {
            "type": "string"
          },
          "endsAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "description": "Dismissals are remembered per `id:updatedAt`"
          },
          "target": {
            "type": "string",
            "enum": ["all", "plans", "organizations"]
          },
          "targetPlans": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "targetOrganizationIds": {
            "description": "`org_…` ids",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": ["scheduled", "active", "ended"]
          },
          "createdAt": {
            "type": "string"
          },
          "createdBy": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AnnouncementAuthorDto"
              }
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "severity",
          "title",
          "body",
          "maintenanceAt",
          "startsAt",
          "endsAt",
          "updatedAt",
          "target",
          "targetPlans",
          "targetOrganizationIds",
          "status",
          "createdAt",
          "createdBy"
        ]
      },
      "AdminAnnouncementListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminAnnouncementDto"
            }
          }
        },
        "required": ["data"]
      },
      "CreateAnnouncementDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["general", "maintenance"],
            "default": "general"
          },
          "severity": {
            "type": "string",
            "enum": ["info", "warning", "critical"],
            "default": "info"
          },
          "title": {
            "type": "string",
            "maxLength": 120
          },
          "body": {
            "type": "string",
            "maxLength": 1000,
            "default": ""
          },
          "maintenanceAt": {
            "type": "string",
            "nullable": true,
            "description": "Required for `maintenance`"
          },
          "startsAt": {
            "type": "string",
            "description": "When the banner starts showing"
          },
          "endsAt": {
            "type": "string",
            "nullable": true,
            "description": "null = until removed"
          },
          "target": {
            "type": "string",
            "enum": ["all", "plans", "organizations"],
            "default": "all"
          },
          "targetPlans": {
            "description": "`plans`: plan codes",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "targetOrganizationIds": {
            "description": "`organizations`: `org_…` ids",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["title", "startsAt"]
      },
      "UpdateAnnouncementDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["general", "maintenance"]
          },
          "severity": {
            "type": "string",
            "enum": ["info", "warning", "critical"]
          },
          "title": {
            "type": "string",
            "maxLength": 120
          },
          "body": {
            "type": "string",
            "maxLength": 1000
          },
          "maintenanceAt": {
            "type": "string",
            "nullable": true,
            "description": "Required for `maintenance`"
          },
          "startsAt": {
            "type": "string"
          },
          "endsAt": {
            "type": "string",
            "nullable": true,
            "description": "null = until removed"
          },
          "target": {
            "type": "string",
            "enum": ["all", "plans", "organizations"]
          },
          "targetPlans": {
            "description": "`plans`: plan codes",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "targetOrganizationIds": {
            "description": "`organizations`: `org_…` ids",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "KnowledgeEmbeddingsStatusDto": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean",
            "description": "An embeddings key is configured in Settings → AI"
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "enum": ["openai", "voyage", "demo"]
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "demo": {
            "type": "boolean",
            "description": "The offline demo embedder is used (development only)"
          }
        },
        "required": ["configured", "provider", "model", "demo"]
      },
      "KnowledgeStatusDto": {
        "type": "object",
        "properties": {
          "planIncludesAi": {
            "type": "boolean",
            "description": "The plan includes the AI assistant (feature `ai`)"
          },
          "planName": {
            "type": "string",
            "nullable": true,
            "description": "Plan name, for the upgrade prompt"
          },
          "embeddings": {
            "$ref": "#/components/schemas/KnowledgeEmbeddingsStatusDto"
          },
          "sources": {
            "type": "number"
          },
          "chunks": {
            "type": "number"
          },
          "staleChunks": {
            "type": "number",
            "description": "Chunks made with another embeddings model (re-embedding)"
          },
          "maxSources": {
            "type": "number"
          },
          "fileMaxBytes": {
            "type": "number"
          },
          "fileTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "application/pdf",
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                "text/plain",
                "text/markdown"
              ]
            }
          }
        },
        "required": [
          "planIncludesAi",
          "planName",
          "embeddings",
          "sources",
          "chunks",
          "staleChunks",
          "maxSources",
          "fileMaxBytes",
          "fileTypes"
        ]
      },
      "KnowledgeSourceSettingsDto": {
        "type": "object",
        "properties": {
          "maxPages": {
            "type": "number",
            "maximum": 500
          },
          "crawlDepth": {
            "type": "number",
            "maximum": 3
          },
          "include": {
            "example": ["/docs/*"],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude": {
            "example": ["/blog/*"],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "schedule": {
            "type": "string",
            "enum": ["off", "daily", "weekly"]
          }
        }
      },
      "FaqEntryDto": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "maxLength": 500
          },
          "answer": {
            "type": "string",
            "maxLength": 10000
          }
        },
        "required": ["question", "answer"]
      },
      "KnowledgeSourceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "kns_…"
          },
          "type": {
            "type": "string",
            "enum": ["url", "sitemap", "file", "faq", "article"]
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "websiteId": {
            "type": "string",
            "nullable": true,
            "description": "`web_…`, or null: every website"
          },
          "status": {
            "type": "string",
            "enum": ["uploading", "pending", "processing", "ready", "error", "needs_key"],
            "description": "`uploading` (file not confirmed yet), `pending`, `processing`, `ready`, `error` (see `error`; earlier chunks stay searchable), `needs_key` (add an embeddings key in Settings → AI)"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "chunkCount": {
            "type": "number"
          },
          "pageCount": {
            "type": "number",
            "description": "Pages fetched in the last sync (URL / sitemap)"
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string",
            "nullable": true
          },
          "sizeBytes": {
            "type": "number",
            "nullable": true
          },
          "settings": {
            "$ref": "#/components/schemas/KnowledgeSourceSettingsDto"
          },
          "content": {
            "type": "string",
            "nullable": true,
            "description": "Article body (detail only)"
          },
          "faq": {
            "nullable": true,
            "description": "FAQ (detail only)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqEntryDto"
            }
          },
          "lastSyncedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "type",
          "title",
          "url",
          "websiteId",
          "status",
          "error",
          "chunkCount",
          "pageCount",
          "fileName",
          "contentType",
          "sizeBytes",
          "settings",
          "lastSyncedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateWebSourceDto": {
        "type": "object",
        "properties": {
          "websiteId": {
            "type": "string",
            "nullable": true,
            "example": "web_…",
            "description": "Only this website's AI agent uses the source (null or absent: every website)"
          },
          "type": {
            "type": "string",
            "enum": ["url", "sitemap"],
            "description": "`url`: one page. `sitemap`: a sitemap.xml, or a page to crawl from"
          },
          "url": {
            "type": "string",
            "example": "https://example.com/help",
            "maxLength": 2048
          },
          "title": {
            "type": "string",
            "maxLength": 200,
            "description": "Defaults to the URL; replaced by the page title on the first sync"
          },
          "maxPages": {
            "type": "number",
            "maximum": 500,
            "default": 100
          },
          "crawlDepth": {
            "type": "number",
            "maximum": 3,
            "default": 2
          },
          "include": {
            "description": "Index only matching URLs (`*` wildcards; `/path` matches the path)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude": {
            "description": "Skip matching URLs",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "schedule": {
            "type": "string",
            "enum": ["off", "daily", "weekly"],
            "default": "off"
          }
        },
        "required": ["type", "url"]
      },
      "CreateFaqSourceDto": {
        "type": "object",
        "properties": {
          "websiteId": {
            "type": "string",
            "nullable": true,
            "example": "web_…",
            "description": "Only this website's AI agent uses the source (null or absent: every website)"
          },
          "title": {
            "type": "string",
            "maxLength": 200,
            "example": "Shipping FAQ"
          },
          "entries": {
            "maxItems": 200,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqEntryDto"
            }
          }
        },
        "required": ["title", "entries"]
      },
      "CreateArticleSourceDto": {
        "type": "object",
        "properties": {
          "websiteId": {
            "type": "string",
            "nullable": true,
            "example": "web_…",
            "description": "Only this website's AI agent uses the source (null or absent: every website)"
          },
          "title": {
            "type": "string",
            "maxLength": 200,
            "example": "Return policy"
          },
          "content": {
            "type": "string",
            "maxLength": 200000,
            "description": "Markdown"
          }
        },
        "required": ["title", "content"]
      },
      "CreateFileSourceDto": {
        "type": "object",
        "properties": {
          "websiteId": {
            "type": "string",
            "nullable": true,
            "example": "web_…",
            "description": "Only this website's AI agent uses the source (null or absent: every website)"
          },
          "fileName": {
            "type": "string",
            "example": "handbook.pdf",
            "maxLength": 255
          },
          "contentType": {
            "type": "string",
            "enum": [
              "application/pdf",
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
              "text/plain",
              "text/markdown"
            ]
          },
          "sizeBytes": {
            "type": "number",
            "maximum": 20971520
          },
          "title": {
            "type": "string",
            "maxLength": 200,
            "description": "Defaults to the file name"
          }
        },
        "required": ["fileName", "contentType", "sizeBytes"]
      },
      "KnowledgeUploadDto": {
        "type": "object",
        "properties": {
          "source": {
            "$ref": "#/components/schemas/KnowledgeSourceDto"
          },
          "uploadUrl": {
            "type": "string",
            "description": "PUT the file bytes here, with `headers`"
          },
          "method": {
            "type": "string",
            "enum": ["PUT"]
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["source", "uploadUrl", "method", "headers", "expiresAt"]
      },
      "UpdateSourceDto": {
        "type": "object",
        "properties": {
          "websiteId": {
            "type": "string",
            "nullable": true,
            "example": "web_…",
            "description": "Only this website's AI agent uses the source (null or absent: every website)"
          },
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "content": {
            "type": "string",
            "description": "Article sources: new body (re-indexed)",
            "maxLength": 200000
          },
          "entries": {
            "description": "FAQ sources: all entries (re-indexed)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqEntryDto"
            }
          },
          "url": {
            "type": "string",
            "description": "URL / sitemap sources (re-indexed when it changes)"
          },
          "maxPages": {
            "type": "number",
            "maximum": 500
          },
          "crawlDepth": {
            "type": "number",
            "maximum": 3
          },
          "include": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "schedule": {
            "type": "string",
            "enum": ["off", "daily", "weekly"]
          }
        }
      },
      "KnowledgeSearchDto": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "example": "How long do refunds take?",
            "maxLength": 2000
          },
          "limit": {
            "type": "number",
            "minimum": 1,
            "maximum": 20,
            "default": 5
          },
          "websiteId": {
            "type": "string",
            "example": "web_…",
            "description": "Search as this website's AI agent would"
          }
        },
        "required": ["query"]
      },
      "KnowledgeHitDto": {
        "type": "object",
        "properties": {
          "chunkId": {
            "type": "string",
            "example": "knc_…"
          },
          "sourceId": {
            "type": "string",
            "example": "kns_…"
          },
          "sourceTitle": {
            "type": "string"
          },
          "sourceUrl": {
            "type": "string",
            "nullable": true
          },
          "sourceType": {
            "type": "string",
            "enum": ["url", "sitemap", "file", "faq", "article"]
          },
          "heading": {
            "type": "string",
            "nullable": true
          },
          "content": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "description": "Reciprocal Rank Fusion score"
          },
          "similarity": {
            "type": "number",
            "nullable": true,
            "description": "Cosine similarity, if matched by vector"
          },
          "matchedBy": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["vector", "keyword"]
            }
          }
        },
        "required": [
          "chunkId",
          "sourceId",
          "sourceTitle",
          "sourceUrl",
          "sourceType",
          "heading",
          "content",
          "score",
          "similarity",
          "matchedBy"
        ]
      },
      "KnowledgeSearchResultDto": {
        "type": "object",
        "properties": {
          "hits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeHitDto"
            }
          },
          "vector": {
            "type": "boolean",
            "description": "False: no embeddings key, keyword search only"
          },
          "embeddingModel": {
            "type": "string",
            "nullable": true
          },
          "tookMs": {
            "type": "number"
          }
        },
        "required": ["hits", "vector", "embeddingModel", "tookMs"]
      },
      "AiSettingsDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Master switch"
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "enum": ["anthropic", "openai"]
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "effort": {
            "type": "string",
            "enum": ["low", "medium", "high"]
          },
          "monthlyCapUsd": {
            "type": "number",
            "nullable": true,
            "description": "Monthly spend cap in USD"
          },
          "embeddingsProvider": {
            "type": "string",
            "nullable": true,
            "enum": ["openai", "voyage"]
          },
          "embeddingsModel": {
            "type": "string",
            "nullable": true
          },
          "embeddingsUseChatKey": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled",
          "provider",
          "model",
          "effort",
          "monthlyCapUsd",
          "embeddingsProvider",
          "embeddingsModel",
          "embeddingsUseChatKey"
        ]
      },
      "AiKeyStatusDto": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean"
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "enum": ["anthropic", "openai", "voyage"]
          },
          "last4": {
            "type": "string",
            "nullable": true,
            "description": "Last 4 characters of the key"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "enum": ["unverified", "active", "failed"]
          },
          "verifiedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastError": {
            "type": "string",
            "nullable": true
          },
          "usesChatKey": {
            "type": "boolean",
            "description": "Embeddings: the OpenAI chat key is used"
          }
        },
        "required": ["configured", "provider", "last4", "status", "verifiedAt", "lastError"]
      },
      "AiModelDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "claude-opus-5-5"
          },
          "name": {
            "type": "string",
            "example": "Claude Opus 5.5"
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": ["id", "name", "createdAt"]
      },
      "AiUsageMonthDto": {
        "type": "object",
        "properties": {
          "month": {
            "type": "string",
            "example": "2026-10-01"
          },
          "replies": {
            "type": "number"
          },
          "handoffs": {
            "type": "number"
          },
          "playgroundRequests": {
            "type": "number"
          },
          "inputTokens": {
            "type": "number"
          },
          "outputTokens": {
            "type": "number"
          },
          "cacheReadTokens": {
            "type": "number"
          },
          "cacheWriteTokens": {
            "type": "number"
          },
          "costUsd": {
            "type": "number",
            "description": "Estimated cost in USD"
          }
        },
        "required": [
          "month",
          "replies",
          "handoffs",
          "playgroundRequests",
          "inputTokens",
          "outputTokens",
          "cacheReadTokens",
          "cacheWriteTokens",
          "costUsd"
        ]
      },
      "AiUsageDto": {
        "type": "object",
        "properties": {
          "current": {
            "$ref": "#/components/schemas/AiUsageMonthDto"
          },
          "months": {
            "description": "The last 6 months, newest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiUsageMonthDto"
            }
          },
          "capUsd": {
            "type": "number",
            "nullable": true
          },
          "paused": {
            "type": "boolean",
            "description": "The cap is reached: the AI hands every chat to the team"
          }
        },
        "required": ["current", "months", "capUsd", "paused"]
      },
      "AiOverviewDto": {
        "type": "object",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "The plan includes the AI assistant (feature `ai`)"
          },
          "demo": {
            "type": "boolean",
            "description": "Development only: replies come from the offline demo provider"
          },
          "settings": {
            "$ref": "#/components/schemas/AiSettingsDto"
          },
          "chatKey": {
            "$ref": "#/components/schemas/AiKeyStatusDto"
          },
          "embeddingsKey": {
            "$ref": "#/components/schemas/AiKeyStatusDto"
          },
          "models": {
            "description": "The chat key’s models (from the last test)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiModelDto"
            }
          },
          "suggestedModel": {
            "type": "string",
            "nullable": true
          },
          "usage": {
            "$ref": "#/components/schemas/AiUsageDto"
          }
        },
        "required": [
          "available",
          "demo",
          "settings",
          "chatKey",
          "embeddingsKey",
          "models",
          "suggestedModel",
          "usage"
        ]
      },
      "UpdateAiSettingsDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "model": {
            "type": "string",
            "description": "A model from the key’s list"
          },
          "effort": {
            "type": "string",
            "enum": ["low", "medium", "high"]
          },
          "monthlyCapUsd": {
            "type": "number",
            "nullable": true,
            "description": "USD per month; null = no cap"
          },
          "embeddingsProvider": {
            "type": "string",
            "enum": ["openai", "voyage"],
            "nullable": true
          },
          "embeddingsModel": {
            "type": "string",
            "nullable": true
          },
          "embeddingsUseChatKey": {
            "type": "boolean"
          }
        }
      },
      "SetChatKeyDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": ["anthropic", "openai"]
          },
          "apiKey": {
            "type": "string",
            "description": "Write-only: never returned"
          }
        },
        "required": ["provider", "apiKey"]
      },
      "SetEmbeddingsKeyDto": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": ["openai", "voyage"]
          },
          "apiKey": {
            "type": "string",
            "description": "Write-only: never returned"
          }
        },
        "required": ["provider", "apiKey"]
      },
      "AiTestResultDto": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiModelDto"
            }
          },
          "suggestedModel": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "auth",
              "quota",
              "rate_limit",
              "overloaded",
              "invalid_request",
              "network",
              "unknown"
            ]
          },
          "key": {
            "$ref": "#/components/schemas/AiKeyStatusDto"
          }
        },
        "required": ["ok", "models", "suggestedModel", "error", "category", "key"]
      },
      "AiModelsDto": {
        "type": "object",
        "properties": {
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiModelDto"
            }
          },
          "suggestedModel": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["models", "suggestedModel"]
      },
      "AiAgentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "aia_…",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          },
          "instructions": {
            "type": "string"
          },
          "greeting": {
            "type": "string",
            "description": "How the AI opens its first reply (empty: no fixed greeting)"
          },
          "mode": {
            "type": "string",
            "enum": ["first", "offline_only", "off"]
          },
          "model": {
            "type": "string",
            "nullable": true,
            "description": "Overrides the settings model"
          },
          "effort": {
            "type": "string",
            "nullable": true,
            "enum": ["low", "medium", "high"]
          },
          "websiteIds": {
            "nullable": true,
            "description": "Websites (web_…) it answers on; null = all",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "handoffKeywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "maxTurns": {
            "type": "number"
          },
          "handoffMessage": {
            "type": "string"
          },
          "knowledgeTool": {
            "type": "boolean",
            "description": "Offer the model a search_knowledge tool"
          }
        },
        "required": [
          "id",
          "name",
          "avatarUrl",
          "instructions",
          "greeting",
          "mode",
          "model",
          "effort",
          "websiteIds",
          "handoffKeywords",
          "maxTurns",
          "handoffMessage",
          "knowledgeTool"
        ]
      },
      "UpdateAiAgentDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true,
            "description": "https URL or a ZebChat avatar"
          },
          "instructions": {
            "type": "string"
          },
          "greeting": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": ["first", "offline_only", "off"]
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "effort": {
            "type": "string",
            "nullable": true,
            "enum": ["low", "medium", "high"]
          },
          "websiteIds": {
            "nullable": true,
            "description": "web_… ids; null = all",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "handoffKeywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "maxTurns": {
            "type": "number"
          },
          "handoffMessage": {
            "type": "string"
          },
          "knowledgeTool": {
            "type": "boolean"
          }
        }
      },
      "PlaygroundMessageDto": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": ["user", "assistant"]
          },
          "text": {
            "type": "string"
          }
        },
        "required": ["role", "text"]
      },
      "PlaygroundRequestDto": {
        "type": "object",
        "properties": {
          "messages": {
            "description": "The test conversation, oldest first",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaygroundMessageDto"
            }
          },
          "requestId": {
            "type": "string",
            "description": "Client-chosen request id"
          }
        },
        "required": ["messages"]
      },
      "AiPlaygroundStartedDto": {
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Matches `ai.playground` events (to this member only)"
          }
        },
        "required": ["requestId"]
      },
      "AiActionParameterDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "order_number",
            "description": "snake_case, unique within the action"
          },
          "type": {
            "type": "string",
            "enum": ["string", "number", "integer", "boolean"]
          },
          "description": {
            "type": "string",
            "example": "The order number from the confirmation email, e.g. A-1042"
          },
          "required": {
            "type": "boolean"
          },
          "enum": {
            "description": "Allowed values (string parameters only)",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["name", "type", "description", "required"]
      },
      "AiActionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "act_…"
          },
          "name": {
            "type": "string",
            "example": "check_order",
            "description": "The tool name the model sees"
          },
          "title": {
            "type": "string",
            "example": "Check order"
          },
          "description": {
            "type": "string",
            "description": "For the model: what it does and when to call it"
          },
          "parameters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiActionParameterDto"
            }
          },
          "url": {
            "type": "string",
            "example": "https://shop.example.com/zebchat/actions"
          },
          "requiresConfirmation": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean"
          },
          "websiteIds": {
            "nullable": true,
            "description": "web_… ids whose chats may use it; null = every website",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lastCalledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "title",
          "description",
          "parameters",
          "url",
          "requiresConfirmation",
          "enabled",
          "websiteIds",
          "lastCalledAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateAiActionDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "check_order"
          },
          "title": {
            "type": "string",
            "example": "Check order"
          },
          "description": {
            "type": "string",
            "example": "Looks up an order’s status and delivery date. Call it when the visitor asks where an order is."
          },
          "parameters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiActionParameterDto"
            }
          },
          "url": {
            "type": "string",
            "example": "https://shop.example.com/zebchat/actions"
          },
          "requiresConfirmation": {
            "type": "boolean",
            "default": false
          },
          "enabled": {
            "type": "boolean",
            "default": false
          },
          "websiteIds": {
            "nullable": true,
            "description": "web_… ids or null (all)",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["name", "title", "description", "parameters", "url"]
      },
      "CreatedAiActionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "act_…"
          },
          "name": {
            "type": "string",
            "example": "check_order",
            "description": "The tool name the model sees"
          },
          "title": {
            "type": "string",
            "example": "Check order"
          },
          "description": {
            "type": "string",
            "description": "For the model: what it does and when to call it"
          },
          "parameters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiActionParameterDto"
            }
          },
          "url": {
            "type": "string",
            "example": "https://shop.example.com/zebchat/actions"
          },
          "requiresConfirmation": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean"
          },
          "websiteIds": {
            "nullable": true,
            "description": "web_… ids whose chats may use it; null = every website",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lastCalledAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "example": "whsec_…",
            "description": "Signing secret for ZebChat-Signature. Shown only here and when rotated"
          }
        },
        "required": [
          "id",
          "name",
          "title",
          "description",
          "parameters",
          "url",
          "requiresConfirmation",
          "enabled",
          "websiteIds",
          "lastCalledAt",
          "createdAt",
          "updatedAt",
          "secret"
        ]
      },
      "AiActionCallDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "acl_…"
          },
          "actionId": {
            "type": "string",
            "nullable": true,
            "example": "act_…"
          },
          "actionName": {
            "type": "string"
          },
          "conversationId": {
            "type": "string",
            "nullable": true,
            "example": "conv_…"
          },
          "source": {
            "type": "string",
            "enum": ["chat", "playground", "eval", "test"]
          },
          "status": {
            "type": "string",
            "enum": ["succeeded", "failed", "invalid", "rate_limited", "cancelled"]
          },
          "request": {
            "type": "string",
            "description": "The arguments (JSON, cut to 1,000 characters)"
          },
          "responseStatus": {
            "type": "number",
            "nullable": true
          },
          "response": {
            "type": "string",
            "nullable": true,
            "description": "First 1,000 characters"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "durationMs": {
            "type": "number",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "actionId",
          "actionName",
          "conversationId",
          "source",
          "status",
          "request",
          "responseStatus",
          "response",
          "error",
          "durationMs",
          "createdAt"
        ]
      },
      "AiActionCallPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiActionCallDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data", "nextCursor"]
      },
      "UpdateAiActionDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "parameters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiActionParameterDto"
            }
          },
          "url": {
            "type": "string"
          },
          "requiresConfirmation": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean"
          },
          "websiteIds": {
            "nullable": true,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AiActionSecretDto": {
        "type": "object",
        "properties": {
          "secret": {
            "type": "string",
            "example": "whsec_…"
          }
        },
        "required": ["secret"]
      },
      "TestAiActionDto": {
        "type": "object",
        "properties": {
          "arguments": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "order_number": "A-1042"
            },
            "description": "Sample arguments, validated against the action’s parameters"
          }
        },
        "required": ["arguments"]
      },
      "AiActionTestResultDto": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "2xx from the endpoint"
          },
          "status": {
            "type": "number",
            "nullable": true
          },
          "durationMs": {
            "type": "number"
          },
          "body": {
            "type": "string",
            "nullable": true,
            "description": "First 16 KB of the response"
          },
          "truncated": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "request": {
            "type": "string",
            "description": "The exact JSON body that was signed and sent"
          },
          "toolResult": {
            "type": "string",
            "description": "What the model would see as the tool result"
          }
        },
        "required": [
          "ok",
          "status",
          "durationMs",
          "body",
          "truncated",
          "error",
          "request",
          "toolResult"
        ]
      },
      "AiReportTotalsDto": {
        "type": "object",
        "properties": {
          "conversations": {
            "type": "number",
            "description": "Chats the AI replied in or handed off"
          },
          "resolvedByAi": {
            "type": "number",
            "description": "Of those: resolved or closed without a handoff or a person taking over"
          },
          "handoffs": {
            "type": "number",
            "description": "Handoffs (all reasons) plus take-overs"
          },
          "handoffRate": {
            "type": "number",
            "description": "handoffs ÷ conversations (0–1)"
          },
          "replies": {
            "type": "number"
          },
          "inputTokens": {
            "type": "number"
          },
          "outputTokens": {
            "type": "number"
          },
          "cacheReadTokens": {
            "type": "number"
          },
          "cacheWriteTokens": {
            "type": "number"
          },
          "costUsd": {
            "type": "number",
            "description": "Estimated, USD"
          },
          "avgLatencyMs": {
            "type": "number",
            "nullable": true,
            "description": "Visitor message → stored answer"
          }
        },
        "required": [
          "conversations",
          "resolvedByAi",
          "handoffs",
          "handoffRate",
          "replies",
          "inputTokens",
          "outputTokens",
          "cacheReadTokens",
          "cacheWriteTokens",
          "costUsd",
          "avgLatencyMs"
        ]
      },
      "AiReportDayDto": {
        "type": "object",
        "properties": {
          "day": {
            "type": "string",
            "example": "2026-09-30"
          },
          "replies": {
            "type": "number"
          },
          "handoffs": {
            "type": "number"
          },
          "tokens": {
            "type": "number"
          },
          "costUsd": {
            "type": "number"
          }
        },
        "required": ["day", "replies", "handoffs", "tokens", "costUsd"]
      },
      "AiReportReasonDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "enum": [
              "tool",
              "keyword",
              "turn_limit",
              "spend_cap",
              "key_error",
              "refusal",
              "provider_error",
              "human"
            ]
          },
          "count": {
            "type": "number"
          }
        },
        "required": ["reason", "count"]
      },
      "AiReportSourceDto": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "example": "kns_…"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Null when the source was deleted"
          },
          "replies": {
            "type": "number",
            "description": "Replies that were given this source"
          }
        },
        "required": ["sourceId", "title", "replies"]
      },
      "AiReportActionDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "calls": {
            "type": "number"
          },
          "succeeded": {
            "type": "number"
          },
          "failed": {
            "type": "number",
            "description": "failed + invalid + rate_limited"
          },
          "cancelled": {
            "type": "number"
          },
          "successRate": {
            "type": "number",
            "nullable": true,
            "description": "succeeded ÷ (succeeded + failed)"
          },
          "avgDurationMs": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "name",
          "calls",
          "succeeded",
          "failed",
          "cancelled",
          "successRate",
          "avgDurationMs"
        ]
      },
      "AiReportFeedbackDto": {
        "type": "object",
        "properties": {
          "up": {
            "type": "number"
          },
          "down": {
            "type": "number"
          },
          "recent": {
            "description": "Newest 20 with a note or a 👎",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiFeedbackItemDto"
            }
          }
        },
        "required": ["up", "down", "recent"]
      },
      "AiReportsDto": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "example": "2026-09-01"
          },
          "to": {
            "type": "string",
            "example": "2026-09-30"
          },
          "timeZone": {
            "type": "string",
            "example": "Europe/Berlin"
          },
          "totals": {
            "$ref": "#/components/schemas/AiReportTotalsDto"
          },
          "days": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiReportDayDto"
            }
          },
          "handoffReasons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiReportReasonDto"
            }
          },
          "topSources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiReportSourceDto"
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiReportActionDto"
            }
          },
          "feedback": {
            "$ref": "#/components/schemas/AiReportFeedbackDto"
          }
        },
        "required": [
          "from",
          "to",
          "timeZone",
          "totals",
          "days",
          "handoffReasons",
          "topSources",
          "actions",
          "feedback"
        ]
      },
      "AiFeedbackDto": {
        "type": "object",
        "properties": {
          "messageId": {
            "type": "string",
            "example": "msg_…"
          },
          "rating": {
            "type": "string",
            "enum": ["up", "down"]
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "userId": {
            "type": "string",
            "example": "usr_…"
          },
          "userName": {
            "type": "string"
          },
          "mine": {
            "type": "boolean",
            "description": "Given by the caller"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["messageId", "rating", "note", "userId", "userName", "mine", "updatedAt"]
      },
      "SetAiFeedbackDto": {
        "type": "object",
        "properties": {
          "rating": {
            "type": "string",
            "enum": ["up", "down"]
          },
          "note": {
            "type": "object",
            "nullable": true,
            "maxLength": 1000
          }
        },
        "required": ["rating"]
      },
      "AiEvalQuestionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evq_…"
          },
          "question": {
            "type": "string"
          },
          "expected": {
            "type": "string",
            "description": "The expected answer or its key facts"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "question", "expected", "createdAt", "updatedAt"]
      },
      "SaveAiEvalQuestionDto": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string",
            "example": "How long do refunds take?"
          },
          "expected": {
            "type": "string",
            "example": "Refunds are paid within 30 days to the original payment method."
          }
        },
        "required": ["question", "expected"]
      },
      "UpdateAiEvalQuestionDto": {
        "type": "object",
        "properties": {
          "question": {
            "type": "string"
          },
          "expected": {
            "type": "string"
          }
        }
      },
      "AiEvalEstimateDto": {
        "type": "object",
        "properties": {
          "questions": {
            "type": "number"
          },
          "provider": {
            "type": "string",
            "nullable": true
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "estimatedCostUsd": {
            "type": "number",
            "description": "Rough upper estimate (answers + grading), USD"
          },
          "blocked": {
            "type": "string",
            "nullable": true,
            "description": "Why a run can’t start now"
          }
        },
        "required": ["questions", "provider", "model", "estimatedCostUsd", "blocked"]
      },
      "AiEvalRunDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evr_…"
          },
          "status": {
            "type": "string",
            "enum": ["queued", "running", "done", "failed"]
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "total": {
            "type": "number"
          },
          "completed": {
            "type": "number"
          },
          "passed": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "estimatedCostUsd": {
            "type": "number"
          },
          "costUsd": {
            "type": "number"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "startedBy": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "model",
          "total",
          "completed",
          "passed",
          "failed",
          "estimatedCostUsd",
          "costUsd",
          "error",
          "startedBy",
          "createdAt",
          "finishedAt"
        ]
      },
      "StartAiEvalRunDto": {
        "type": "object",
        "properties": {
          "confirm": {
            "type": "boolean",
            "description": "Must be true: the run spends the organization’s own tokens (see the estimate)"
          }
        },
        "required": ["confirm"]
      },
      "AiEvalResultDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evs_…"
          },
          "questionId": {
            "type": "string",
            "nullable": true,
            "example": "evq_…"
          },
          "question": {
            "type": "string"
          },
          "expected": {
            "type": "string"
          },
          "answer": {
            "type": "string",
            "nullable": true
          },
          "passed": {
            "type": "boolean",
            "nullable": true,
            "description": "Null: not answered or not graded"
          },
          "verdict": {
            "type": "string",
            "nullable": true,
            "description": "The grader’s reasoning"
          },
          "handoff": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "costUsd": {
            "type": "number"
          }
        },
        "required": [
          "id",
          "questionId",
          "question",
          "expected",
          "answer",
          "passed",
          "verdict",
          "handoff",
          "error",
          "costUsd"
        ]
      },
      "AiEvalRunDetailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evr_…"
          },
          "status": {
            "type": "string",
            "enum": ["queued", "running", "done", "failed"]
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "total": {
            "type": "number"
          },
          "completed": {
            "type": "number"
          },
          "passed": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "estimatedCostUsd": {
            "type": "number"
          },
          "costUsd": {
            "type": "number"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "startedBy": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AiEvalResultDto"
            }
          }
        },
        "required": [
          "id",
          "status",
          "model",
          "total",
          "completed",
          "passed",
          "failed",
          "estimatedCostUsd",
          "costUsd",
          "error",
          "startedBy",
          "createdAt",
          "finishedAt",
          "results"
        ]
      },
      "ContactSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ctc_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "company": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string",
            "enum": ["widget_form", "set_user", "manual", "import"]
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagDto"
            }
          },
          "visitorCount": {
            "type": "number",
            "description": "Linked visitors (browsers, devices)"
          },
          "conversationCount": {
            "type": "number",
            "description": "Conversations of the linked visitors"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "phone",
          "company",
          "source",
          "firstSeenAt",
          "lastSeenAt",
          "createdAt",
          "updatedAt",
          "tags",
          "visitorCount",
          "conversationCount"
        ]
      },
      "ContactPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactSummaryDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          },
          "total": {
            "type": "number",
            "description": "Contacts matching the filters (all pages)"
          }
        },
        "required": ["data", "nextCursor", "total"]
      },
      "CreateContactDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Unique per organization"
          },
          "phone": {
            "type": "string",
            "maxLength": 64
          },
          "company": {
            "type": "string",
            "maxLength": 200
          },
          "notes": {
            "type": "string",
            "maxLength": 10000
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom attributes: a flat object (at most 50 keys of letters, digits, `_ . -`) of strings, numbers, booleans or null"
          },
          "tagIds": {
            "example": ["tag_…"],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "listIds": {
            "example": ["cls_…"],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "visitorId": {
            "type": "string",
            "example": "vis_…",
            "description": "Create the contact from this visitor: links it, and name/email/phone default to the visitor’s"
          }
        }
      },
      "ContactListRefDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cls_…"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "name"]
      },
      "ContactLinkedVisitorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "vis_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "verified": {
            "type": "boolean"
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "websiteId", "name", "email", "verified", "firstSeenAt", "lastSeenAt"]
      },
      "ContactConversationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "conv_…"
          },
          "visitorId": {
            "type": "string",
            "example": "vis_…"
          },
          "websiteId": {
            "type": "string",
            "example": "web_…"
          },
          "status": {
            "type": "string"
          },
          "lastMessagePreview": {
            "type": "string",
            "nullable": true
          },
          "lastMessageAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "rating": {
            "type": "number",
            "nullable": true,
            "description": "The visitor’s 1–5 rating"
          }
        },
        "required": [
          "id",
          "visitorId",
          "websiteId",
          "status",
          "lastMessagePreview",
          "lastMessageAt",
          "createdAt",
          "rating"
        ]
      },
      "ContactStatsDto": {
        "type": "object",
        "properties": {
          "visits": {
            "type": "number"
          },
          "pageviews": {
            "type": "number"
          },
          "conversations": {
            "type": "number"
          },
          "lastVisitAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": ["visits", "pageviews", "conversations", "lastVisitAt"]
      },
      "ContactDetailDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ctc_…"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "company": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string",
            "enum": ["widget_form", "set_user", "manual", "import"]
          },
          "firstSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagDto"
            }
          },
          "visitorCount": {
            "type": "number",
            "description": "Linked visitors (browsers, devices)"
          },
          "conversationCount": {
            "type": "number",
            "description": "Conversations of the linked visitors"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true
          },
          "lists": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactListRefDto"
            }
          },
          "visitors": {
            "description": "Most recently seen first (50)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactLinkedVisitorDto"
            }
          },
          "conversations": {
            "description": "Newest first (50)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactConversationDto"
            }
          },
          "stats": {
            "$ref": "#/components/schemas/ContactStatsDto"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "phone",
          "company",
          "source",
          "firstSeenAt",
          "lastSeenAt",
          "createdAt",
          "updatedAt",
          "tags",
          "visitorCount",
          "conversationCount",
          "notes",
          "attributes",
          "lists",
          "visitors",
          "conversations",
          "stats"
        ]
      },
      "ContactBulkDto": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": ["delete", "add_to_list", "remove_from_list", "add_tag", "remove_tag"]
          },
          "contactIds": {
            "example": ["ctc_…"],
            "maxItems": 1000,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "listId": {
            "type": "string",
            "example": "cls_…",
            "description": "For add_to_list / remove_from_list"
          },
          "tagId": {
            "type": "string",
            "example": "tag_…",
            "description": "For add_tag / remove_tag"
          }
        },
        "required": ["action", "contactIds"]
      },
      "ContactBulkResultDto": {
        "type": "object",
        "properties": {
          "affected": {
            "type": "number",
            "description": "Contacts changed (or deleted)"
          }
        },
        "required": ["affected"]
      },
      "UpdateContactDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "nullable": true,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "maxLength": 64
          },
          "company": {
            "type": "string",
            "nullable": true,
            "maxLength": 200
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "maxLength": 10000
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom attributes: a flat object (at most 50 keys of letters, digits, `_ . -`) of strings, numbers, booleans or null. Replaces all attributes."
          }
        }
      },
      "MergeContactDto": {
        "type": "object",
        "properties": {
          "contactId": {
            "type": "string",
            "example": "ctc_…",
            "description": "The contact merged into this one and then deleted: its visitors, lists and tags move over, empty fields are filled from it"
          }
        },
        "required": ["contactId"]
      },
      "SetContactTagsDto": {
        "type": "object",
        "properties": {
          "tagIds": {
            "example": ["tag_…"],
            "description": "Replaces the tags",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["tagIds"]
      },
      "ContactVisitorDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string",
            "example": "vis_…"
          }
        },
        "required": ["visitorId"]
      },
      "ContactListDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cls_…"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "memberCount": {
            "type": "number"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "description", "memberCount", "createdAt", "updatedAt"]
      },
      "CreateContactListDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 500
          }
        },
        "required": ["name"]
      },
      "UpdateContactListDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 500
          }
        }
      },
      "ContactIdsDto": {
        "type": "object",
        "properties": {
          "contactIds": {
            "example": ["ctc_…"],
            "maxItems": 1000,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["contactIds"]
      },
      "ContactImportErrorDto": {
        "type": "object",
        "properties": {
          "row": {
            "type": "number",
            "description": "Data row (1 = the first row after the header)"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string"
          }
        },
        "required": ["row", "email", "error"]
      },
      "ContactImportDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cim_…"
          },
          "status": {
            "type": "string",
            "enum": ["uploading", "queued", "processing", "completed", "failed"]
          },
          "fileName": {
            "type": "string"
          },
          "sizeBytes": {
            "type": "number"
          },
          "mode": {
            "type": "string",
            "enum": ["update", "skip"]
          },
          "columns": {
            "type": "array",
            "items": {
              "type": "string",
              "nullable": true
            }
          },
          "listId": {
            "type": "string",
            "nullable": true,
            "example": "cls_…"
          },
          "tagIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "totalRows": {
            "type": "number"
          },
          "processedRows": {
            "type": "number"
          },
          "created": {
            "type": "number"
          },
          "updated": {
            "type": "number"
          },
          "skipped": {
            "type": "number"
          },
          "failed": {
            "type": "number",
            "description": "Rows that could not be imported"
          },
          "errors": {
            "description": "The first 1,000 row errors",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactImportErrorDto"
            }
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Why the whole import failed"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "fileName",
          "sizeBytes",
          "mode",
          "columns",
          "listId",
          "tagIds",
          "totalRows",
          "processedRows",
          "created",
          "updated",
          "skipped",
          "failed",
          "errors",
          "error",
          "createdAt",
          "startedAt",
          "completedAt"
        ]
      },
      "CreateContactImportDto": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "example": "customers.csv"
          },
          "sizeBytes": {
            "type": "number",
            "description": "At most 10485760 bytes"
          }
        },
        "required": ["fileName", "sizeBytes"]
      },
      "ContactImportUploadDto": {
        "type": "object",
        "properties": {
          "import": {
            "$ref": "#/components/schemas/ContactImportDto"
          },
          "uploadUrl": {
            "type": "string",
            "description": "PUT the CSV bytes here, with `headers`"
          },
          "method": {
            "type": "string",
            "example": "PUT"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["import", "uploadUrl", "method", "headers", "expiresAt"]
      },
      "StartContactImportDto": {
        "type": "object",
        "properties": {
          "columns": {
            "type": "array",
            "items": {
              "type": "string",
              "nullable": true
            },
            "example": ["name", "email", null, "attribute:plan"],
            "description": "Per CSV column, in header order: `name`, `first_name`, `last_name`, `email`, `phone`, `company`, `notes`, `tags`, `attribute:<key>`, or null to ignore it"
          },
          "hasHeader": {
            "type": "boolean",
            "default": true,
            "description": "The first row is a header (skipped)"
          },
          "mode": {
            "type": "string",
            "enum": ["update", "skip"],
            "default": "update",
            "description": "Existing contacts (same email): fill in the fields from the file, or leave them"
          },
          "listId": {
            "type": "string",
            "example": "cls_…",
            "description": "Add every imported contact to this list"
          },
          "tagIds": {
            "example": ["tag_…"],
            "description": "Tag every imported contact",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["columns"]
      },
      "AutomationRuleDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "aut_…"
          },
          "name": {
            "type": "string",
            "example": "Tag pricing questions"
          },
          "enabled": {
            "type": "boolean"
          },
          "trigger": {
            "type": "string",
            "enum": [
              "conversation_started",
              "visitor_message",
              "visitor_idle",
              "agent_idle",
              "conversation_assigned",
              "conversation_closed",
              "offline_message",
              "tag_added",
              "visitor_on_site"
            ]
          },
          "triggerConfig": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "idleMinutes": 30
            },
            "description": "`idleMinutes` (idle triggers), `seconds` (`visitor_on_site`, 5–86400), `tagId` (`tag_added`, optional)"
          },
          "match": {
            "type": "string",
            "enum": ["all", "any"]
          },
          "conditions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "example": [
              {
                "type": "message_text",
                "op": "contains_any",
                "words": ["price", "quote"]
              }
            ],
            "description": "Conditions (0–20), each `{type, …}` with `type` one of website, visitor_country, page_url, message_text, visitor_email, visitor_identified, business_hours, agents_available, team, assignment, tags, priority, returning_visitor. See docs/API.md#automations"
          },
          "actions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "example": [
              {
                "type": "add_tags",
                "tagIds": ["tag_…"]
              }
            ],
            "description": "Actions in order (1–10), each `{type, …}` with `type` one of send_message, add_note, add_tags, remove_tags, set_priority, assign_team, assign_agent, close_conversation, notify_email. See docs/API.md#automations"
          },
          "websiteId": {
            "type": "string",
            "nullable": true,
            "description": "web_…, or null for every website"
          },
          "position": {
            "type": "number",
            "description": "Evaluation order (ascending)"
          },
          "stopAfterMatch": {
            "type": "boolean",
            "description": "When it matched, later rules skip the same event"
          },
          "lastRunAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastRunStatus": {
            "type": "string",
            "nullable": true,
            "enum": ["succeeded", "partial", "failed", "skipped"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "enabled",
          "trigger",
          "triggerConfig",
          "match",
          "conditions",
          "actions",
          "websiteId",
          "position",
          "stopAfterMatch",
          "lastRunAt",
          "lastRunStatus",
          "createdAt",
          "updatedAt"
        ]
      },
      "AutomationListDto": {
        "type": "object",
        "properties": {
          "data": {
            "description": "In evaluation order",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AutomationRuleDto"
            }
          },
          "featureAvailable": {
            "type": "boolean",
            "description": "The plan includes automations. Without it rules are kept but never run, and only switching off and deleting work"
          },
          "maxRules": {
            "type": "number",
            "example": 50
          }
        },
        "required": ["data", "featureAvailable", "maxRules"]
      },
      "CreateAutomationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Tag pricing questions",
            "maxLength": 80
          },
          "trigger": {
            "type": "string",
            "enum": [
              "conversation_started",
              "visitor_message",
              "visitor_idle",
              "agent_idle",
              "conversation_assigned",
              "conversation_closed",
              "offline_message",
              "tag_added",
              "visitor_on_site"
            ]
          },
          "triggerConfig": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "idleMinutes": 30
            }
          },
          "match": {
            "type": "string",
            "enum": ["all", "any"],
            "default": "all"
          },
          "conditions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Conditions (0–20), each `{type, …}` with `type` one of website, visitor_country, page_url, message_text, visitor_email, visitor_identified, business_hours, agents_available, team, assignment, tags, priority, returning_visitor. See docs/API.md#automations"
          },
          "actions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Actions in order (1–10), each `{type, …}` with `type` one of send_message, add_note, add_tags, remove_tags, set_priority, assign_team, assign_agent, close_conversation, notify_email. See docs/API.md#automations"
          },
          "enabled": {
            "type": "boolean",
            "default": true
          },
          "websiteId": {
            "type": "string",
            "nullable": true,
            "description": "web_…, or null (all)"
          },
          "stopAfterMatch": {
            "type": "boolean",
            "default": false
          }
        },
        "required": ["name", "trigger", "actions"]
      },
      "AutomationActionResultDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "send_message",
              "add_note",
              "add_tags",
              "remove_tags",
              "set_priority",
              "assign_team",
              "assign_agent",
              "close_conversation",
              "notify_email"
            ]
          },
          "ok": {
            "type": "boolean"
          },
          "error": {
            "type": "string"
          }
        },
        "required": ["type", "ok"]
      },
      "AutomationRunDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "aur_…"
          },
          "ruleId": {
            "type": "string",
            "nullable": true,
            "example": "aut_…",
            "description": "Null once deleted"
          },
          "ruleName": {
            "type": "string",
            "description": "The rule’s name at the time"
          },
          "conversationId": {
            "type": "string",
            "nullable": true,
            "example": "conv_…",
            "description": "The chat. `visitor_on_site` runs: the chat the rule’s message started, or null (none, or deleted)"
          },
          "visitorId": {
            "type": "string",
            "nullable": true,
            "example": "vis_…",
            "description": "`visitor_on_site` runs: the visitor (null for chat runs)"
          },
          "trigger": {
            "type": "string",
            "enum": [
              "conversation_started",
              "visitor_message",
              "visitor_idle",
              "agent_idle",
              "conversation_assigned",
              "conversation_closed",
              "offline_message",
              "tag_added",
              "visitor_on_site"
            ]
          },
          "status": {
            "type": "string",
            "enum": ["succeeded", "partial", "failed", "skipped"]
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AutomationActionResultDto"
            }
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "ruleId",
          "ruleName",
          "conversationId",
          "visitorId",
          "trigger",
          "status",
          "actions",
          "error",
          "createdAt"
        ]
      },
      "AutomationRunPageDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AutomationRunDto"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          }
        },
        "required": ["data", "nextCursor"]
      },
      "ReorderAutomationsDto": {
        "type": "object",
        "properties": {
          "ids": {
            "example": ["aut_…", "aut_…"],
            "description": "Every rule of the organization, in the new order",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["ids"]
      },
      "UpdateAutomationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "trigger": {
            "type": "string",
            "enum": [
              "conversation_started",
              "visitor_message",
              "visitor_idle",
              "agent_idle",
              "conversation_assigned",
              "conversation_closed",
              "offline_message",
              "tag_added",
              "visitor_on_site"
            ]
          },
          "triggerConfig": {
            "type": "object",
            "additionalProperties": true
          },
          "match": {
            "type": "string",
            "enum": ["all", "any"]
          },
          "conditions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Conditions (0–20), each `{type, …}` with `type` one of website, visitor_country, page_url, message_text, visitor_email, visitor_identified, business_hours, agents_available, team, assignment, tags, priority, returning_visitor. See docs/API.md#automations"
          },
          "actions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Actions in order (1–10), each `{type, …}` with `type` one of send_message, add_note, add_tags, remove_tags, set_priority, assign_team, assign_agent, close_conversation, notify_email. See docs/API.md#automations"
          },
          "enabled": {
            "type": "boolean"
          },
          "websiteId": {
            "type": "string",
            "nullable": true,
            "description": "web_…, or null (all)"
          },
          "stopAfterMatch": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
