{
  "openapi": "3.1.0",
  "info": {
    "title": "Avelto API",
    "description": "Public REST API for the Avelto AI sales assistant platform. Manage agents, channels, conversations, leads, knowledge sources, and outbound webhooks programmatically. All requests authenticate with a workspace-scoped API token issued from /app/settings/api-tokens.",
    "version": "0.0.1",
    "contact": {
      "email": "hello@avelto.pl",
      "url": "https://avelto.pl"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.avelto.pl/api/v1",
      "description": "Production"
    },
    {
      "url": "http://localhost:3001/api/v1",
      "description": "Local development"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Conversations",
      "description": "List, fetch, and bulk-manage conversation threads."
    },
    {
      "name": "Leads",
      "description": "Pipeline-stage CRUD for captured leads."
    },
    {
      "name": "Agents",
      "description": "Workspace AI agents and their publish state."
    },
    {
      "name": "Channels",
      "description": "Inbound channels (website / Telegram / WhatsApp / etc)."
    },
    {
      "name": "Knowledge",
      "description": "Upload files or crawl URLs into the knowledge base."
    },
    {
      "name": "Webhooks",
      "description": "Outbound webhook subscriptions (lead/conversation events)."
    },
    {
      "name": "Widget",
      "description": "Public widget endpoints — no API token; uses session JWT."
    }
  ],
  "paths": {
    "/conversations": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "operationId": "listConversations",
        "summary": "List conversations",
        "description": "Paginated conversation list. Supports filtering by agentId, channelId, status, and a comma-separated list of tagIds.",
        "parameters": [
          {
            "name": "agentId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "channelId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "OPEN",
                "HANDOFF_REQUESTED",
                "HANDED_OFF",
                "CLOSED"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "tagIds",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated UUIDs"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Conversation"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "Conversations"
        ],
        "operationId": "getConversation",
        "summary": "Fetch a conversation",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{id}/operator-message": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": [
          "Conversations"
        ],
        "operationId": "sendOperatorMessage",
        "summary": "Send an operator-authored message",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperatorMessage"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "404": {
            "description": "Conversation not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/conversations/bulk": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "operationId": "bulkConversationAction",
        "summary": "Bulk close / reopen / assign / tag conversations",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkConversationAction"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Action result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "updated": {
                      "type": "integer"
                    },
                    "skipped": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/leads": {
      "get": {
        "tags": [
          "Leads"
        ],
        "operationId": "listLeads",
        "summary": "List leads",
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "score"
              ],
              "default": "newest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Lead"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Leads"
        ],
        "operationId": "createLead",
        "summary": "Create a lead",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLead"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leads/{id}/status": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "patch": {
        "tags": [
          "Leads"
        ],
        "operationId": "updateLeadStatus",
        "summary": "Update lead pipeline status",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLeadStatus"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            }
          },
          "404": {
            "description": "Lead not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/leads/bulk-update": {
      "post": {
        "tags": [
          "Leads"
        ],
        "operationId": "bulkUpdateLeads",
        "summary": "Bulk update lead statuses",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids",
                  "status"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "NEW",
                      "QUALIFIED",
                      "CONTACTED",
                      "WON",
                      "LOST"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/leads/bulk-delete": {
      "post": {
        "tags": [
          "Leads"
        ],
        "operationId": "bulkDeleteLeads",
        "summary": "Bulk soft-delete leads",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/agents": {
      "get": {
        "tags": [
          "Agents"
        ],
        "operationId": "listAgents",
        "summary": "List agents",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Agent"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Agents"
        ],
        "operationId": "createAgent",
        "summary": "Create an agent (OWNER role only)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAgent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "403": {
            "description": "OWNER role required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/agents/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "Agents"
        ],
        "operationId": "getAgent",
        "summary": "Fetch an agent",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Agents"
        ],
        "operationId": "updateAgent",
        "summary": "Update an agent (OWNER role only)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAgent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Agents"
        ],
        "operationId": "deleteAgent",
        "summary": "Delete an agent",
        "responses": {
          "204": {
            "description": "Deleted"
          }
        }
      }
    },
    "/agents/{id}/publish": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": [
          "Agents"
        ],
        "operationId": "publishAgent",
        "summary": "Publish an agent",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          }
        }
      }
    },
    "/channels": {
      "get": {
        "tags": [
          "Channels"
        ],
        "operationId": "listChannels",
        "summary": "List channels",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Channel"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/channels/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "delete": {
        "tags": [
          "Channels"
        ],
        "operationId": "deleteChannel",
        "summary": "Delete a channel",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/knowledge/sources": {
      "get": {
        "tags": [
          "Knowledge"
        ],
        "operationId": "listKnowledgeSources",
        "summary": "List knowledge sources",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/knowledge/upload": {
      "post": {
        "tags": [
          "Knowledge"
        ],
        "operationId": "uploadKnowledgeFile",
        "summary": "Upload a file (PDF / DOCX / TXT / HTML / MD)",
        "description": "Raw bytes in the request body. Set Content-Type to one of the supported MIMEs and X-Original-Name to the visible filename. Max 10 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "text/html": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "text/plain": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "text/markdown": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "X-Original-Name",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeJob"
                }
              }
            }
          }
        }
      }
    },
    "/knowledge/crawl": {
      "post": {
        "tags": [
          "Knowledge"
        ],
        "operationId": "crawlKnowledgeUrl",
        "summary": "Crawl a URL into the knowledge base",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeJob"
                }
              }
            }
          }
        }
      }
    },
    "/integrations": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listIntegrations",
        "summary": "List integrations (includes webhooks)",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/integrations/webhook": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhookIntegration",
        "summary": "Subscribe to outbound webhook events",
        "description": "Returns the freshly minted signing secret EXACTLY ONCE. Receivers verify HMAC-SHA256(secret, \"<unix>.<body>\") against the X-Convo-Signature header.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookIntegration"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookIntegration"
                }
              }
            }
          }
        }
      }
    },
    "/integrations/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteIntegration",
        "summary": "Soft-delete an integration / webhook",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/widget/session": {
      "post": {
        "tags": [
          "Widget"
        ],
        "operationId": "widgetBootstrapSession",
        "summary": "Anonymous widget session bootstrap",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "workspaceId",
                  "agentId"
                ],
                "properties": {
                  "workspaceId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "agentId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "clientFingerprint": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 128
                  },
                  "preferredLocale": {
                    "type": "string",
                    "enum": [
                      "en",
                      "pl",
                      "uk",
                      "ru"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session token + initial conversation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessionToken": {
                      "type": "string"
                    },
                    "conversationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "convo_<32 hex>",
        "description": "Workspace-scoped API token. Mint one at /app/settings/api-tokens. Tokens look like `convo_` followed by 32 hex chars and carry a fixed set of scopes (e.g. leads:read, conversations:write)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "statusCode",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer",
            "example": 400
          },
          "message": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "error": {
            "type": "string",
            "example": "Bad Request"
          }
        }
      },
      "Conversation": {
        "type": "object",
        "required": [
          "id",
          "status",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agentId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "channelId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "HANDOFF_REQUESTED",
              "HANDED_OFF",
              "CLOSED"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "id",
          "conversationId",
          "role",
          "content",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "conversationId": {
            "type": "string",
            "format": "uuid"
          },
          "role": {
            "type": "string",
            "enum": [
              "USER",
              "ASSISTANT",
              "SYSTEM",
              "TOOL"
            ]
          },
          "content": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Lead": {
        "type": "object",
        "required": [
          "id",
          "status",
          "fields",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "NEW",
              "QUALIFIED",
              "CONTACTED",
              "WON",
              "LOST"
            ]
          },
          "fields": {
            "type": "object",
            "additionalProperties": true
          },
          "score": {
            "type": "integer",
            "nullable": true,
            "minimum": 0,
            "maximum": 100
          },
          "conversationId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "crmExternalId": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateLead": {
        "type": "object",
        "required": [
          "fields"
        ],
        "properties": {
          "conversationId": {
            "type": "string",
            "format": "uuid"
          },
          "endUserId": {
            "type": "string",
            "format": "uuid"
          },
          "source": {
            "type": "string",
            "maxLength": 120
          },
          "fields": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "UpdateLeadStatus": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "NEW",
              "QUALIFIED",
              "CONTACTED",
              "WON",
              "LOST"
            ]
          }
        }
      },
      "Agent": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "systemPrompt": {
            "type": "string"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tone": {
            "type": "string",
            "nullable": true
          },
          "modelProvider": {
            "type": "string",
            "enum": [
              "openai",
              "anthropic",
              "mistral",
              "groq",
              "xai"
            ]
          },
          "modelName": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string",
            "enum": [
              "general",
              "sales",
              "support",
              "billing",
              "technical"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PUBLISHED",
              "ARCHIVED"
            ]
          }
        }
      },
      "CreateAgent": {
        "type": "object",
        "required": [
          "name",
          "systemPrompt"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "systemPrompt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20000
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 2,
              "maxLength": 8
            },
            "default": [
              "en"
            ]
          },
          "tone": {
            "type": "string",
            "maxLength": 120
          },
          "modelProvider": {
            "type": "string",
            "enum": [
              "openai",
              "anthropic",
              "mistral",
              "groq",
              "xai"
            ],
            "default": "openai"
          },
          "modelName": {
            "type": "string",
            "maxLength": 120
          },
          "role": {
            "type": "string",
            "enum": [
              "general",
              "sales",
              "support",
              "billing",
              "technical"
            ],
            "default": "general"
          }
        }
      },
      "UpdateAgent": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateAgent"
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "DRAFT",
                  "PUBLISHED",
                  "ARCHIVED"
                ]
              }
            }
          }
        ]
      },
      "Channel": {
        "type": "object",
        "required": [
          "id",
          "type",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "WEBSITE",
              "TELEGRAM",
              "WHATSAPP",
              "MESSENGER",
              "VIBER",
              "EMAIL",
              "SLACK",
              "DISCORD",
              "SMS",
              "VOICE"
            ]
          },
          "name": {
            "type": "string"
          },
          "agentId": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "KnowledgeJob": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "UPLOAD",
              "CRAWL"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "PROCESSING",
              "READY",
              "FAILED"
            ]
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CrawlRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "depth": {
            "type": "integer",
            "enum": [
              0,
              1,
              2
            ],
            "default": 1
          },
          "sameOriginOnly": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "WebhookIntegration": {
        "type": "object",
        "required": [
          "id",
          "type",
          "url",
          "events"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "WEBHOOK"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "lead.created",
                "lead.qualified",
                "conversation.closed",
                "conversation.ended",
                "handoff.requested",
                "message.operator_sent",
                "webhook.test"
              ]
            }
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "signingSecret": {
            "type": "string",
            "description": "Plaintext HMAC signing secret. Returned ONLY on create — subsequent reads omit this field. Store it securely."
          }
        }
      },
      "CreateWebhookIntegration": {
        "type": "object",
        "required": [
          "type",
          "url",
          "events"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "WEBHOOK"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "secret": {
            "type": "string",
            "minLength": 8
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "lead.created",
                "lead.qualified",
                "conversation.closed",
                "conversation.ended",
                "handoff.requested",
                "message.operator_sent",
                "webhook.test"
              ]
            }
          }
        }
      },
      "OperatorMessage": {
        "type": "object",
        "required": [
          "content"
        ],
        "properties": {
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          }
        }
      },
      "BulkConversationAction": {
        "type": "object",
        "required": [
          "ids",
          "action"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 200
          },
          "action": {
            "type": "string",
            "enum": [
              "close",
              "reopen",
              "assign",
              "tag",
              "untag"
            ]
          },
          "params": {
            "type": "object",
            "properties": {
              "operatorId": {
                "type": "string",
                "format": "uuid"
              },
              "tagId": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        }
      }
    }
  }
}
