{
  "openapi": "3.0.3",
  "info": {
    "title": "Cliengo Public API",
    "version": "1.0",
    "description": "API pública unificada de Cliengo. Punto de entrada único para gestionar contactos,\nconversaciones, canales, chatbots, planes, usuarios y plantillas de WhatsApp.\n\n---\n\n## Obtener tu Token\n\n1. Ingresá a [dash.cliengo.com/integrations/connect_api](https://dash.cliengo.com/integrations/connect_api)\n2. Generá un nuevo **Token** seleccionando los permisos que necesites\n3. Copiá tu token (formato `sk_test_...` en stage, `sk_live_...` en producción)\n\n---\n\n## Autenticación\n\nTodas las requests requieren el header `Authorization: Bearer <token>`.\n\n```bash\ncurl -H \"Authorization: Bearer TU_TOKEN\" https://connect.cliengo.com/v1/plans\n```\n\nSi recibís un JSON con planes, tu token funciona.\n\n---\n\n## Rate Limiting\n\n**1000 requests por minuto** por token. Cada respuesta incluye:\n\n| Header | Significado |\n|--------|-------------|\n| `X-RateLimit-Limit` | Máximo por ventana |\n| `X-RateLimit-Remaining` | Restantes |\n| `X-RateLimit-Reset` | Unix timestamp del reset |\n\nSi excedés el límite → HTTP **429** con header `Retry-After`.\n\n---\n\n## Errores comunes\n\n| Código | Causa | Solución |\n|--------|-------|----------|\n| 401 | Falta header de auth o token inválido | Verificá tu `Authorization: Bearer` header |\n| 404 | Endpoint no existe | Revisá la URL |\n| 429 | Rate limit excedido | Esperá `Retry-After` segundos |\n\n---\n\n## Trazabilidad\n\nCada respuesta incluye `X-Request-ID` (UUID). Podés enviar tu propio valor\nen el request para correlacionar logs.\n",
    "contact": {
      "name": "Cliengo Engineering",
      "email": "hola@cliengo.com",
      "url": "https://cliengo.com"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://connect.cliengo.com",
      "description": "Producción"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Token de autenticación (formato `sk_live_...`).\nObtener token en [dash.cliengo.com/integrations/connect_api](https://dash.cliengo.com/integrations/connect_api).\n"
      }
    },
    "schemas": {
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "60a1b2c3d4e5f6a7b8c9d0e1"
          },
          "name": {
            "type": "string",
            "example": "Juan Pérez"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "juan@example.com"
          },
          "phone": {
            "type": "string",
            "example": "+5491155551234"
          },
          "internationalPhoneNumber": {
            "type": "string",
            "example": "5491155551234"
          },
          "channelId": {
            "type": "string",
            "description": "ID del canal donde se originó el contacto"
          },
          "companyId": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "active",
              "client",
              "long_term"
            ]
          },
          "subStatus": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "Último mensaje del contacto"
          },
          "assignedTo": {
            "type": "string",
            "nullable": true,
            "description": "ID del agente asignado"
          },
          "rating": {
            "type": "integer"
          },
          "entryMethod": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "example": 1
          },
          "limit": {
            "type": "integer",
            "example": 20
          },
          "total": {
            "type": "integer",
            "example": 42
          },
          "totalPages": {
            "type": "integer",
            "example": 3
          },
          "hasNext": {
            "type": "boolean"
          },
          "hasPrev": {
            "type": "boolean"
          }
        }
      },
      "ContactSearchResponse": {
        "type": "object",
        "properties": {
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          }
        }
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true,
            "example": "626e9cc66ac98128162b2bbc"
          },
          "channelId": {
            "type": "string",
            "example": "5f08e255c9a881002afc06ec"
          },
          "companyId": {
            "type": "string",
            "readOnly": true,
            "example": "5c7414a4e4b06f6eb79408f5"
          },
          "channel": {
            "$ref": "#/components/schemas/Channel"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "CLOSED"
            ]
          },
          "lastMessage": {
            "type": "string",
            "readOnly": true,
            "example": "será un placer asistirte, cuál es tu nombre?"
          },
          "lastMessageAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "visitorName": {
            "type": "string",
            "example": "Robert"
          },
          "visitorEmail": {
            "type": "string",
            "example": "robert@example.com"
          },
          "visitorPhone": {
            "type": "string",
            "example": "584122233456"
          },
          "participants": {
            "type": "array",
            "readOnly": true,
            "items": {
              "$ref": "#/components/schemas/Participant"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "closed": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        }
      },
      "Channel": {
        "type": "string",
        "enum": [
          "FACEBOOK",
          "WEB",
          "WHATSAPP",
          "INSTAGRAM"
        ]
      },
      "Participant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "robot",
              "visitor",
              "user"
            ]
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true
          },
          "user": {
            "type": "string",
            "readOnly": true
          },
          "text": {
            "type": "string",
            "example": "Hola, necesito ayuda"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "image_url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "edited": {
            "type": "boolean",
            "readOnly": true
          }
        }
      },
      "ConversationListResponse": {
        "type": "object",
        "properties": {
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Conversation"
            }
          }
        }
      },
      "ChannelSite": {
        "type": "object",
        "description": "Vista de un canal (sitio/integración) en el modelo omnichannel. El campo\n`id` es el identificador del canal (compatible con el `channelId`\nlegacy = websiteId). Reemplazó a la respuesta legacy\n`{ id, title, url, company, enabled, integrations }` del backend\nanterior. El chatbot asociado se incluye embebido — usar su `id` para\noperar contra `/v1/chatbots/{chatbotId}`.\n",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID del canal (== websiteId histórico)."
          },
          "type": {
            "type": "string",
            "enum": [
              "WEBSITE",
              "WHATSAPP_API",
              "WHATSAPP_BUSINESS",
              "FACEBOOK",
              "INSTAGRAM"
            ],
            "description": "Tipo del canal."
          },
          "label": {
            "type": "string",
            "description": "Nombre legible (título del sitio, número de WhatsApp, page de FB, etc.)."
          },
          "connected": {
            "type": "boolean",
            "description": "Indica si el canal está conectado y recibiendo mensajes."
          },
          "testChannelUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL para probar el chatbot en este canal."
          },
          "chatbot": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ChatbotSummary"
              }
            ],
            "nullable": true,
            "description": "Chatbot asignado al canal (resumen). `null` si ninguno."
          },
          "whatsappForm": {
            "type": "boolean",
            "description": "Solo aplica a canales WhatsApp — indica si el formulario de configuración está activo."
          },
          "disconnectionRequested": {
            "type": "boolean",
            "description": "Solo WhatsApp API — indica que se está procesando la desconexión."
          }
        }
      },
      "ChatbotSummary": {
        "type": "object",
        "description": "Resumen del chatbot devuelto cuando se incluye dentro de un canal.",
        "properties": {
          "id": {
            "type": "string"
          },
          "chatbotWithAi": {
            "type": "boolean",
            "description": "True si alguna pregunta del flujo o el `globalFulfillment` apunta a un endpoint de IA (zordon)."
          },
          "isMuted": {
            "type": "boolean"
          },
          "title": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "connectedChannels": {
            "type": "integer"
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "CLIENGO_STARTER"
          },
          "name": {
            "type": "string",
            "example": "Leads Cliengo Starter"
          },
          "description": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "annualPlan": {
            "type": "boolean"
          },
          "leadLimit": {
            "type": "integer"
          },
          "conversationLimit": {
            "type": "integer"
          },
          "channelLimit": {
            "type": "integer"
          },
          "userLimit": {
            "type": "integer"
          },
          "priceUSD": {
            "type": "number"
          },
          "priceARS": {
            "type": "number"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "plan": {
            "type": "string"
          },
          "features": {
            "type": "object"
          },
          "statuses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "Chatbot": {
        "type": "object",
        "description": "Vista del chatbot en el modelo omnichannel. El `id` ahora es el\nidentificador propio del chatbot (no el websiteId/channelId, como\nera en la versión legacy del backend). Para asignarlo a uno o más\ncanales usá `PUT /v1/chatbots/{chatbotId}/channels`.\n",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID del chatbot. Diferente al channelId — un chatbot puede asignarse a múltiples canales."
          },
          "chatbotWithAi": {
            "type": "boolean",
            "description": "True si alguna pregunta del flujo o el `globalFulfillment` apunta a un endpoint de IA (zordon)."
          },
          "isMuted": {
            "type": "boolean",
            "description": "Cuando es true, el chatbot no responde mensajes (los visitantes pasan directo a operador)."
          },
          "title": {
            "type": "string",
            "description": "Título visible del chatbot (mostrado al visitante)."
          },
          "name": {
            "type": "string",
            "description": "Nombre interno del chatbot."
          },
          "channels": {
            "type": "array",
            "description": "Canales actualmente asignados a este chatbot.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "testChatbotUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL para probar el chatbot en un widget de prueba."
          }
        }
      },
      "Trigger": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "conditions": {
            "type": "object"
          },
          "actions": {
            "type": "object"
          }
        }
      },
      "WhatsAppTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "ID interno de la plantilla",
            "example": 170
          },
          "elementName": {
            "type": "string",
            "description": "Nombre identificador de la plantilla",
            "example": "promo_belleza_personalizada"
          },
          "status": {
            "type": "string",
            "enum": [
              "APPROVED",
              "PENDING",
              "REJECTED"
            ],
            "description": "Estado de aprobación en Meta"
          },
          "category": {
            "type": "string",
            "enum": [
              "MARKETING",
              "UTILITY",
              "AUTHENTICATION"
            ],
            "description": "Categoría de la plantilla"
          },
          "text": {
            "type": "string",
            "description": "Contenido del mensaje con variables ({name}, {1}, etc.)"
          },
          "language": {
            "type": "string",
            "description": "Código de idioma (es, en, pt, etc.)"
          },
          "components": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "WhatsAppCampaign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "SCHEDULED",
              "SENDING",
              "SENT",
              "STOPPED",
              "CANCELLED"
            ]
          },
          "templateId": {
            "type": "string"
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time"
          },
          "sentCount": {
            "type": "integer"
          },
          "failedCount": {
            "type": "integer"
          }
        }
      },
      "WhatsAppEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "destination": {
            "type": "string",
            "description": "Número de teléfono del destinatario"
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "delivered",
              "read",
              "failed",
              "invalid",
              "enqueued",
              "pending"
            ]
          },
          "failureCode": {
            "type": "string",
            "nullable": true
          },
          "failureReason": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WhatsAppCampaignFull": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WhatsAppCampaign"
          },
          {
            "type": "object",
            "properties": {
              "events": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/WhatsAppEvent"
                }
              },
              "eventCounter": {
                "type": "object",
                "properties": {
                  "pending": {
                    "type": "integer"
                  },
                  "enqueued": {
                    "type": "integer"
                  },
                  "failed": {
                    "type": "integer"
                  },
                  "sent": {
                    "type": "integer"
                  },
                  "delivered": {
                    "type": "integer"
                  },
                  "read": {
                    "type": "integer"
                  },
                  "answered": {
                    "type": "integer"
                  },
                  "invalid": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        ]
      },
      "Note": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OperatorTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          }
        }
      },
      "Phase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          }
        }
      },
      "FeaturesResponse": {
        "type": "object",
        "properties": {
          "features": {
            "type": "object",
            "description": "Mapa de features habilitadas y sus valores",
            "additionalProperties": true,
            "example": {
              "livechat": true,
              "whatsapp": true,
              "campaigns": false
            }
          }
        }
      },
      "Integration": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "config": {
            "type": "object"
          }
        }
      },
      "PhaseCount": {
        "type": "object",
        "properties": {
          "phaseId": {
            "type": "string"
          },
          "phaseName": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "description": "Tipo de evento al que se puede suscribir un webhook. Formato: `categoría/acción`.\n",
        "enum": [
          "conversation/created",
          "conversation/updated",
          "conversation/deleted",
          "conversation/operator_assigned",
          "conversation/message",
          "conversation/note",
          "conversation/archived",
          "conversation/contact",
          "conversation/phase_changed",
          "conversation/tag_added",
          "conversation/tag_removed",
          "contact/created",
          "contact/updated",
          "contact/status_changed",
          "contact/operator_assigned",
          "contact/tag_added",
          "contact/deleted"
        ]
      },
      "WebhookSubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "60a1b2c3d4e5f6a7b8c9d0e1"
          },
          "companyId": {
            "type": "string"
          },
          "websiteId": {
            "type": "string",
            "description": "ID del canal o `*` para todos los canales",
            "example": "*"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://tu-servidor.com/webhook"
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "example": [
              "conversation/created",
              "contact/created"
            ]
          },
          "isActive": {
            "type": "boolean",
            "example": true
          },
          "secret": {
            "type": "string",
            "description": "Token secreto enviado en el header `X-Webhook-Secret` de cada entrega",
            "example": "whsec_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456"
          },
          "retryCount": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "description": "Cantidad máxima de reintentos en caso de fallo (backoff exponencial)",
            "example": 5
          },
          "customHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Headers personalizados enviados con cada entrega",
            "example": {
              "X-Custom-Key": "valor"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url",
          "eventTypes"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL donde Cliengo enviará los eventos via POST",
            "example": "https://tu-servidor.com/webhook"
          },
          "eventTypes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "Eventos a los que suscribirse (al menos uno)",
            "example": [
              "conversation/created",
              "conversation/message"
            ]
          },
          "websiteId": {
            "type": "string",
            "description": "ID del canal. Usar `*` o omitir para recibir eventos de todos los canales",
            "default": "*"
          },
          "retryCount": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "default": 5,
            "description": "Reintentos en caso de fallo (0 = sin reintentos, máximo 10)"
          },
          "customHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Headers extra a incluir en cada entrega"
          }
        }
      },
      "UpdateWebhookRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "isActive": {
            "type": "boolean"
          },
          "retryCount": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10
          },
          "customHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "WebhookDeliveryLog": {
        "type": "object",
        "description": "Registro de un intento de entrega de un webhook.",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "event": {
            "type": "string",
            "description": "Tipo de evento entregado",
            "example": "conversation/created"
          },
          "payload": {
            "type": "object",
            "description": "Body JSON enviado al endpoint"
          },
          "statusCode": {
            "type": "integer",
            "nullable": true,
            "description": "HTTP status de la respuesta (null si no hubo respuesta)",
            "example": 200
          },
          "responseBody": {
            "type": "string",
            "nullable": true,
            "description": "Body de la respuesta del servidor"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true,
            "description": "Mensaje de error (null si exitoso)"
          },
          "success": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "parameters": {
      "LimitParam": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 20,
          "maximum": 100
        },
        "description": "Resultados por página"
      },
      "OffsetParam": {
        "name": "offset",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 0
        },
        "description": "Offset de paginación"
      },
      "PageParam": {
        "name": "page",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 1
        },
        "description": "Número de página"
      },
      "webhookId": {
        "name": "webhookId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "ID del webhook"
      }
    }
  },
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "operationId": "healthCheck",
        "security": [],
        "tags": [
          "System"
        ],
        "responses": {
          "200": {
            "description": "Gateway operativo",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ok"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "summary": "Buscar contactos",
        "operationId": "searchContacts",
        "tags": [
          "Contacts"
        ],
        "description": "Búsqueda de contactos con filtros avanzados.",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Búsqueda fuzzy en nombre, email y teléfono"
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por email (búsqueda parcial)"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por nombre (búsqueda parcial)"
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por teléfono (búsqueda parcial)"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "active",
                "client",
                "long_term"
              ]
            },
            "description": "Filtrar por estado del contacto"
          },
          {
            "name": "subStatus",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por sub-estado"
          },
          {
            "name": "websiteId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por canal (IDs separados por coma)"
          },
          {
            "name": "assignedTo",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por agente asignado (IDs separados por coma, o UNASSIGNED)"
          },
          {
            "name": "entryMethod",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por método de entrada (WEB, WHATSAPP, FACEBOOK, etc.)"
          },
          {
            "name": "conversationTags",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por tags de conversación (separados por coma)"
          },
          {
            "name": "rating",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por calificación (valores separados por coma)"
          },
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Contactos creados después de esta fecha (ISO 8601)"
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Contactos creados antes de esta fecha (ISO 8601)"
          },
          {
            "name": "lastUpdateDateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Contactos actualizados después de esta fecha (ISO 8601)"
          },
          {
            "name": "lastUpdateDateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Contactos actualizados antes de esta fecha (ISO 8601)"
          },
          {
            "name": "orderBy",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "_id"
            },
            "description": "Campo para ordenar (ej: creationDate, name, email)"
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Dirección de ordenamiento"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            },
            "description": "Número de página"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Resultados de la búsqueda",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactSearchResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear contacto",
        "operationId": "createContact",
        "tags": [
          "Contacts"
        ],
        "description": "Crea un nuevo contacto.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "websiteId",
                  "name"
                ],
                "properties": {
                  "websiteId": {
                    "type": "string",
                    "description": "ID del canal donde se origina el contacto"
                  },
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "internationalPhoneNumber": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "new",
                      "active",
                      "client",
                      "long_term"
                    ]
                  },
                  "entryMethod": {
                    "type": "string"
                  },
                  "assignedTo": {
                    "type": "string",
                    "description": "ID del agente a asignar"
                  },
                  "note": {
                    "type": "string",
                    "description": "Nota inicial del contacto"
                  },
                  "customFields": {
                    "type": "object",
                    "description": "Campos personalizados (key-value)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contacto creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/bulk-delete": {
      "post": {
        "summary": "Eliminar contactos en lote",
        "operationId": "bulkDeleteContacts",
        "tags": [
          "Contacts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contacts"
                ],
                "properties": {
                  "contacts": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array de IDs de contactos a eliminar"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "207": {
            "description": "Resultado por cada contacto (Multi-Status)"
          }
        }
      }
    },
    "/v1/contacts/{contactId}": {
      "get": {
        "summary": "Obtener contacto",
        "operationId": "getContact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle del contacto",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Actualizar contacto",
        "operationId": "patchContact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string"
                  },
                  "assignedTo": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contacto actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar contacto",
        "operationId": "deleteContact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contacto eliminado"
          }
        }
      }
    },
    "/v1/contacts/{contactId}/notes": {
      "get": {
        "summary": "Listar notas del contacto",
        "operationId": "listContactNotes",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de notas"
          }
        }
      },
      "post": {
        "summary": "Agregar nota al contacto",
        "operationId": "createContactNote",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nota creada"
          }
        }
      }
    },
    "/v1/contacts/{contactId}/notes/{noteId}": {
      "patch": {
        "summary": "Actualizar nota",
        "operationId": "patchContactNote",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "noteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nota actualizada"
          }
        }
      },
      "delete": {
        "summary": "Eliminar nota",
        "operationId": "deleteContactNote",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "noteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Nota eliminada"
          }
        }
      }
    },
    "/v1/contacts/{contactId}/tags": {
      "post": {
        "summary": "Agregar tag al contacto",
        "operationId": "addContactTag",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag agregado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{contactId}/history": {
      "get": {
        "summary": "Historial del contacto",
        "operationId": "getContactHistory",
        "tags": [
          "Contacts"
        ],
        "description": "Logs y notas del contacto combinados.",
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Historial del contacto"
          }
        }
      }
    },
    "/v1/conversations": {
      "get": {
        "summary": "Listar conversaciones",
        "operationId": "listConversations",
        "tags": [
          "Conversations"
        ],
        "description": "Conversaciones de la empresa autenticada, con filtros avanzados y paginación.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "opened",
                "closed",
                "inactive"
              ]
            },
            "description": "Estado de la conversación"
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por tags (separados por coma)"
          },
          {
            "name": "fromDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de inicio (ISO 8601)"
          },
          {
            "name": "toDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de fin (ISO 8601)"
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por canal (separados por coma, valores: WEB, WHATSAPP, FACEBOOK, INSTAGRAM)"
          },
          {
            "name": "phase",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID de la fase"
          },
          {
            "name": "agent",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID del usuario/agente asignado"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Búsqueda de texto libre"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/OffsetParam"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Campo y orden de ordenamiento (ej: createdAt:desc)"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de conversaciones",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear conversación",
        "operationId": "createConversation",
        "tags": [
          "Conversations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "channelId",
                  "companyId",
                  "channel",
                  "from"
                ],
                "properties": {
                  "channelId": {
                    "type": "string"
                  },
                  "companyId": {
                    "type": "string"
                  },
                  "channel": {
                    "$ref": "#/components/schemas/Channel"
                  },
                  "from": {
                    "type": "string",
                    "description": "Identificador del originante"
                  },
                  "url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación creada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/by-phase": {
      "get": {
        "summary": "Conversaciones agrupadas por fase",
        "operationId": "listConversationsByPhase",
        "tags": [
          "Conversations"
        ],
        "description": "Agrupa las conversaciones por fase del pipeline. Soporta los mismos filtros que el listado de conversaciones.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "opened",
                "closed",
                "inactive"
              ]
            },
            "description": "Estado de la conversación"
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por tags (separados por coma)"
          },
          {
            "name": "fromDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de inicio (ISO 8601)"
          },
          {
            "name": "toDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de fin (ISO 8601)"
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por canal (separados por coma, valores: WEB, WHATSAPP, FACEBOOK, INSTAGRAM)"
          },
          {
            "name": "phase",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID de la fase"
          },
          {
            "name": "agent",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID del usuario/agente asignado"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Búsqueda de texto libre"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/OffsetParam"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Campo y orden de ordenamiento (ej: createdAt:desc)"
          }
        ],
        "responses": {
          "200": {
            "description": "Conversaciones agrupadas por fase",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "phases": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "phase": {
                            "$ref": "#/components/schemas/Phase"
                          },
                          "conversations": {
                            "$ref": "#/components/schemas/ConversationListResponse"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/export": {
      "get": {
        "summary": "Exportar conversaciones",
        "operationId": "exportConversations",
        "tags": [
          "Conversations"
        ],
        "description": "Exporta conversaciones en formato descargable.",
        "responses": {
          "200": {
            "description": "Archivo de exportación"
          }
        }
      }
    },
    "/v1/conversations/channels/list": {
      "get": {
        "summary": "Listar canales activos",
        "operationId": "listConversationChannels",
        "tags": [
          "Conversations"
        ],
        "description": "Devuelve los canales con conversaciones activas.",
        "responses": {
          "200": {
            "description": "Lista de canales",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Channel"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/contact/{contactId}": {
      "get": {
        "summary": "Conversaciones de un contacto",
        "operationId": "getConversationsByContact",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "contactId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversaciones del contacto",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Conversation"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}": {
      "get": {
        "summary": "Obtener conversación",
        "operationId": "getConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle de la conversación",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "404": {
            "description": "No encontrada"
          }
        }
      },
      "put": {
        "summary": "Actualizar conversación",
        "operationId": "updateConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Conversation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación actualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Actualizar contexto de conversación",
        "operationId": "patchConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación parcialmente actualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar conversación",
        "operationId": "deleteConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversación eliminada"
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/messages": {
      "get": {
        "summary": "Listar mensajes",
        "operationId": "listConversationMessages",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeCommands",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Incluir mensajes de tipo comando"
          }
        ],
        "responses": {
          "200": {
            "description": "Mensajes de la conversación",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Message"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Enviar mensaje",
        "operationId": "addConversationMessage",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from",
                  "fromType",
                  "type"
                ],
                "properties": {
                  "body": {
                    "type": "string",
                    "example": "Hola, necesito ayuda"
                  },
                  "fromType": {
                    "type": "string",
                    "enum": [
                      "user",
                      "robot",
                      "visitor"
                    ]
                  },
                  "from": {
                    "type": "string",
                    "description": "ID del remitente"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "image",
                      "text/plain",
                      "command",
                      "note"
                    ]
                  },
                  "message": {
                    "type": "object",
                    "description": "Para mensajes multimedia",
                    "properties": {
                      "url": {
                        "type": "string"
                      },
                      "caption": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mensaje enviado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/assign": {
      "post": {
        "summary": "Asignar a operador",
        "operationId": "assignConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assignedTo"
                ],
                "properties": {
                  "assignedTo": {
                    "type": "string",
                    "description": "ID del operador"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación asignada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/transfer": {
      "post": {
        "summary": "Transferir conversación",
        "operationId": "transferConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "transferTo"
                ],
                "properties": {
                  "transferTo": {
                    "type": "string",
                    "description": "ID del operador destino"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación transferida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/close": {
      "post": {
        "summary": "Cerrar conversación",
        "operationId": "closeConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "isLead"
                ],
                "properties": {
                  "isLead": {
                    "type": "boolean",
                    "description": "Si la conversación resultó en un lead"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación cerrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/open": {
      "post": {
        "summary": "Reabrir conversación",
        "operationId": "openConversation",
        "tags": [
          "Conversations"
        ],
        "description": "Reabre una conversación cerrada (status → ACTIVE).",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversación reabierta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/mark": {
      "post": {
        "summary": "Marcar conversación (leída/no leída)",
        "operationId": "markConversation",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "read": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversación marcada"
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/contact": {
      "put": {
        "summary": "Actualizar datos del contacto de la conversación",
        "operationId": "updateConversationContact",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contacto actualizado"
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/notes": {
      "get": {
        "summary": "Listar notas de una conversación",
        "operationId": "listConversationNotes",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de notas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Note"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Agregar nota a conversación",
        "operationId": "createConversationNote",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string",
                    "description": "Contenido de la nota"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Tags opcionales para la nota"
                  },
                  "quote": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "IDs de mensajes citados"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Nota creada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tags": {
      "get": {
        "summary": "Listar tags",
        "operationId": "listTags",
        "tags": [
          "Tags"
        ],
        "description": "Devuelve todos los tags de operador de la empresa.",
        "responses": {
          "200": {
            "description": "Lista de tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OperatorTag"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear tag",
        "operationId": "createTag",
        "tags": [
          "Tags"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tag creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTag"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tags/{tagId}": {
      "put": {
        "summary": "Actualizar tag",
        "operationId": "updateTag",
        "tags": [
          "Tags"
        ],
        "parameters": [
          {
            "name": "tagId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "color": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTag"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar tag",
        "operationId": "deleteTag",
        "tags": [
          "Tags"
        ],
        "parameters": [
          {
            "name": "tagId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tag eliminado"
          }
        }
      }
    },
    "/v1/phases": {
      "get": {
        "summary": "Listar fases",
        "operationId": "listPhases",
        "tags": [
          "Phases"
        ],
        "description": "Fases del pipeline de conversaciones.",
        "responses": {
          "200": {
            "description": "Lista de fases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Phase"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear fase",
        "operationId": "createPhase",
        "tags": [
          "Phases"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "order": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Fase creada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Phase"
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/counts": {
      "get": {
        "summary": "Conteo por fase",
        "operationId": "getPhaseCounts",
        "tags": [
          "Phases"
        ],
        "description": "Cantidad de conversaciones en cada fase. Soporta los mismos filtros que el listado de conversaciones.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "opened",
                "closed",
                "inactive"
              ]
            },
            "description": "Estado de la conversación"
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por tags (separados por coma)"
          },
          {
            "name": "fromDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de inicio (ISO 8601)"
          },
          {
            "name": "toDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fecha de fin (ISO 8601)"
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por canal (separados por coma, valores: WEB, WHATSAPP, FACEBOOK, INSTAGRAM)"
          },
          {
            "name": "phase",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID de la fase"
          },
          {
            "name": "agent",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID del usuario/agente asignado"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Búsqueda de texto libre"
          }
        ],
        "responses": {
          "200": {
            "description": "Conteos por fase",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PhaseCount"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{phaseId}": {
      "put": {
        "summary": "Actualizar fase",
        "operationId": "updatePhase",
        "tags": [
          "Phases"
        ],
        "parameters": [
          {
            "name": "phaseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "order": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fase actualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Phase"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar fase",
        "operationId": "deletePhase",
        "tags": [
          "Phases"
        ],
        "parameters": [
          {
            "name": "phaseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fase eliminada"
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/phases/{phaseId}": {
      "patch": {
        "summary": "Asignar fase a conversación",
        "operationId": "assignPhaseToConversation",
        "tags": [
          "Phases"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phaseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fase asignada"
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "summary": "Info de la cuenta",
        "operationId": "getAccount",
        "tags": [
          "Accounts"
        ],
        "responses": {
          "200": {
            "description": "Datos de la cuenta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Actualizar cuenta",
        "operationId": "updateAccount",
        "tags": [
          "Accounts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cuenta actualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/plan": {
      "get": {
        "summary": "Plan de la cuenta",
        "operationId": "getAccountPlan",
        "tags": [
          "Accounts"
        ],
        "responses": {
          "200": {
            "description": "Plan actual de la cuenta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plan"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/features": {
      "get": {
        "summary": "Features de la cuenta",
        "operationId": "getAccountFeatures",
        "tags": [
          "Accounts"
        ],
        "responses": {
          "200": {
            "description": "Features habilitadas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeaturesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/integrations": {
      "get": {
        "summary": "Integraciones de la cuenta",
        "operationId": "getAccountIntegrations",
        "tags": [
          "Accounts"
        ],
        "responses": {
          "200": {
            "description": "Lista de integraciones configuradas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Integration"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/channels": {
      "get": {
        "summary": "Listar canales",
        "operationId": "listChannels",
        "tags": [
          "Channels"
        ],
        "description": "Lista los canales activos de la cuenta. Los canales eliminados no se\nincluyen. La lista NO está paginada — devuelve un array directo.\n",
        "responses": {
          "200": {
            "description": "Lista de canales",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ChannelSite"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear canal",
        "operationId": "createChannel",
        "tags": [
          "Channels"
        ],
        "description": "Crea un nuevo canal según su tipo.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "WEBSITE",
                      "WHATSAPP_API",
                      "WHATSAPP_BUSINESS",
                      "FACEBOOK",
                      "INSTAGRAM"
                    ]
                  },
                  "businessName": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Solo para canales WEBSITE."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Solo para canales WhatsApp."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Canal creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelSite"
                }
              }
            }
          }
        }
      }
    },
    "/v1/channels/{channelId}": {
      "get": {
        "summary": "Obtener canal",
        "operationId": "getChannel",
        "tags": [
          "Channels"
        ],
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID del canal (== websiteId histórico)."
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle del canal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelSite"
                }
              }
            }
          },
          "404": {
            "description": "No encontrado"
          }
        }
      },
      "patch": {
        "summary": "Actualizar canal parcialmente",
        "operationId": "patchChannel",
        "tags": [
          "Channels"
        ],
        "description": "Actualiza propiedades del canal (label/title, etc.). Los campos\nprotegidos (`_id`, `companyId`, `creationDate`) son ignorados\nsilenciosamente.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canal parcialmente actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelSite"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Asignar / desasignar chatbot al canal",
        "operationId": "assignChatbotToChannel",
        "tags": [
          "Channels"
        ],
        "description": "Asocia (`ADD`) o desasocia (`REMOVE`) un chatbot al canal. Un canal\npuede tener un solo chatbot a la vez — `ADD` desasocia automáticamente\ncualquier otro chatbot previamente asignado.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chatbotId",
                  "action"
                ],
                "properties": {
                  "chatbotId": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "ADD",
                      "REMOVE"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Asignación actualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelSite"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar canal",
        "operationId": "deleteChannel",
        "tags": [
          "Channels"
        ],
        "description": "Elimina el canal (soft-delete) y desasocia cualquier chatbot. Para\ncanales tipo Meta (FB/IG/WA Business) además dispara la desconexión\nen la plataforma origen.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Canal eliminado"
          }
        }
      }
    },
    "/v1/channels/{channelId}/disconnect": {
      "post": {
        "summary": "Solicitar desconexión de un canal WhatsApp",
        "operationId": "disconnectChannel",
        "tags": [
          "Channels"
        ],
        "description": "Solicita la desconexión del canal en la plataforma origen. Hoy solo\nsoportado para canales tipo `WHATSAPP_API` — marca el canal con\n`disconnectionRequested: true`.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Desconexión solicitada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelSite"
                }
              }
            }
          },
          "400": {
            "description": "Tipo de canal no soportado para desconexión"
          }
        }
      }
    },
    "/v1/users": {
      "get": {
        "summary": "Listar usuarios",
        "operationId": "listUsers",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/OffsetParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de usuarios",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear usuario",
        "operationId": "createUser",
        "tags": [
          "Users"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Usuario creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/me": {
      "get": {
        "summary": "Obtener usuario actual",
        "operationId": "getCurrentUser",
        "tags": [
          "Users"
        ],
        "responses": {
          "200": {
            "description": "Datos del usuario autenticado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/roles": {
      "get": {
        "summary": "Listar roles",
        "operationId": "listUserRoles",
        "tags": [
          "Users"
        ],
        "responses": {
          "200": {
            "description": "Roles disponibles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "example": [
                    "admin",
                    "operator",
                    "viewer"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{userId}": {
      "get": {
        "summary": "Obtener usuario",
        "operationId": "getUser",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Datos del usuario",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Actualizar usuario",
        "operationId": "updateUser",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Usuario actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Actualizar usuario parcialmente",
        "operationId": "patchUser",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Usuario parcialmente actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar usuario",
        "operationId": "deleteUser",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usuario eliminado"
          }
        }
      }
    },
    "/v1/users/invite": {
      "post": {
        "summary": "Invitar usuario",
        "operationId": "inviteUser",
        "tags": [
          "Users"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invitación enviada"
          }
        }
      }
    },
    "/v1/plans": {
      "get": {
        "summary": "Listar planes",
        "operationId": "listPlans",
        "tags": [
          "Plans"
        ],
        "description": "Todos los planes disponibles de Cliengo.",
        "responses": {
          "200": {
            "description": "Lista de planes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "paging": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Plan"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/plans/active": {
      "get": {
        "summary": "Planes activos",
        "operationId": "getActivePlans",
        "tags": [
          "Plans"
        ],
        "description": "Solo los planes actualmente disponibles para contratar.",
        "responses": {
          "200": {
            "description": "Lista de planes activos",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Plan"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/plans/{planId}": {
      "get": {
        "summary": "Obtener plan",
        "operationId": "getPlan",
        "tags": [
          "Plans"
        ],
        "parameters": [
          {
            "name": "planId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle del plan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plan"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chatbots": {
      "get": {
        "summary": "Listar chatbots",
        "operationId": "listChatbots",
        "tags": [
          "Chatbots"
        ],
        "description": "Lista todos los chatbots de la cuenta (no paginado).",
        "responses": {
          "200": {
            "description": "Lista de chatbots",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Chatbot"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear chatbot",
        "operationId": "createChatbot",
        "tags": [
          "Chatbots"
        ],
        "description": "Crea un chatbot a partir del template base de la cuenta. Empieza\nsin canales asignados — usá `PUT /v1/chatbots/{chatbotId}/channels`\npara asignarlos.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Título visible. Default \"Chatbot\"."
                  },
                  "name": {
                    "type": "string",
                    "description": "Nombre interno. Default \"Pilar\"."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Chatbot creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chatbot"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chatbots/{chatbotId}": {
      "get": {
        "summary": "Obtener chatbot",
        "operationId": "getChatbot",
        "tags": [
          "Chatbots"
        ],
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID propio del chatbot. **Atención**: con la migración omnichannel\nya no es el `websiteId/channelId` — para encontrar el `chatbotId`\nde un canal, usá `GET /v1/channels/{channelId}` y leé `chatbot.id`\nen la respuesta.\n"
          }
        ],
        "responses": {
          "200": {
            "description": "Configuración del chatbot",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chatbot"
                }
              }
            }
          },
          "404": {
            "description": "Chatbot no encontrado"
          }
        }
      },
      "patch": {
        "summary": "Actualizar propiedades del chatbot",
        "operationId": "patchChatbot",
        "tags": [
          "Chatbots"
        ],
        "description": "Actualiza `isMuted`, `title` o `name`. Para asignar/desasignar canales\nusá `PUT /v1/chatbots/{chatbotId}/channels`.\n",
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isMuted": {
                    "type": "boolean",
                    "description": "Mutear (true) / desmutear (false) el chatbot."
                  },
                  "title": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chatbot actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chatbot"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Eliminar chatbot",
        "operationId": "deleteChatbot",
        "tags": [
          "Chatbots"
        ],
        "description": "Soft-delete del chatbot. No elimina los canales asociados.",
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Chatbot eliminado"
          }
        }
      }
    },
    "/v1/chatbots/{chatbotId}/channels": {
      "put": {
        "summary": "Asignar / desasignar / limpiar canales del chatbot",
        "operationId": "updateChatbotChannels",
        "tags": [
          "Chatbots"
        ],
        "description": "Aplica una operación atómica sobre la lista de canales del chatbot:\n\n- `ADD` — agrega `channelId` a la lista (si ya está, no duplica).\n- `REMOVE` — quita `channelId` de la lista.\n- `CLEAN` — vacía toda la lista. En este caso `channelId` puede omitirse.\n",
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "ADD",
                      "REMOVE",
                      "CLEAN"
                    ]
                  },
                  "channelId": {
                    "type": "string",
                    "description": "Requerido cuando `action` es `ADD` o `REMOVE`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canales actualizados",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chatbot"
                }
              }
            }
          },
          "400": {
            "description": "channelId requerido para ADD/REMOVE"
          }
        }
      }
    },
    "/v1/chatbots/{chatbotId}/business-hours-config": {
      "get": {
        "summary": "Obtener configuración de horario de atención del chatbot",
        "operationId": "getChatbotBusinessHoursConfig",
        "tags": [
          "Chatbots"
        ],
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuración de horarios",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Actualizar horario de atención del chatbot",
        "operationId": "patchChatbotBusinessHoursConfig",
        "tags": [
          "Chatbots"
        ],
        "parameters": [
          {
            "name": "chatbotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled",
                  "businessHours",
                  "initialMessage",
                  "finalSalutation"
                ],
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "businessHours": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "range",
                        "days"
                      ],
                      "properties": {
                        "range": {
                          "type": "string",
                          "description": "Rango horario, ej. `09:00-18:00`."
                        },
                        "days": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 6
                          },
                          "description": "Días de la semana (0 = domingo)."
                        }
                      }
                    }
                  },
                  "initialMessage": {
                    "type": "string"
                  },
                  "finalSalutation": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Horarios actualizados",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp": {
      "get": {
        "summary": "Listar canales con WhatsApp",
        "operationId": "listWhatsAppChannels",
        "tags": [
          "WhatsApp"
        ],
        "description": "Canales vinculados al token con configuración WhatsApp.",
        "responses": {
          "200": {
            "description": "Lista de canales"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/templates": {
      "get": {
        "summary": "Listar plantillas WhatsApp",
        "operationId": "listWhatsAppTemplates",
        "tags": [
          "WhatsApp"
        ],
        "description": "Devuelve las plantillas HSM aprobadas, pendientes y rechazadas del canal.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID del canal de WhatsApp (websiteId)"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de plantillas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "example": "SUCCESS"
                    },
                    "statusCode": {
                      "type": "integer",
                      "example": 200
                    },
                    "result": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WhatsAppTemplate"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear plantilla WhatsApp",
        "operationId": "createWhatsAppTemplate",
        "tags": [
          "WhatsApp"
        ],
        "description": "Envía una nueva plantilla para aprobación del proveedor (Meta/Gupshup). El resultado inicial queda en estado `pending`; al aprobarse pasa a `approved`.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "languageCode",
                  "category",
                  "type",
                  "text"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Identificador único de la plantilla dentro del canal.",
                    "example": "registro_cliengo"
                  },
                  "languageCode": {
                    "type": "string",
                    "example": "es"
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "MARKETING",
                      "UTILITY",
                      "AUTHENTICATION"
                    ]
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "TEXT",
                      "IMAGE",
                      "VIDEO",
                      "DOCUMENT"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "description": "Cuerpo de la plantilla con placeholders `{name}`, `{code}`, etc."
                  },
                  "description": {
                    "type": "string"
                  },
                  "mediaId": {
                    "type": "string",
                    "description": "ID devuelto por `POST /template-media` cuando `type` es IMAGE/VIDEO/DOCUMENT."
                  },
                  "buttons": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Plantilla creada (pendiente aprobación)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppTemplate"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/templates/{templateId}": {
      "put": {
        "summary": "Actualizar plantilla WhatsApp",
        "operationId": "updateWhatsAppTemplate",
        "tags": [
          "WhatsApp"
        ],
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "templateId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Plantilla actualizada"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns": {
      "post": {
        "summary": "Crear campaña WhatsApp",
        "operationId": "createWhatsAppCampaign",
        "tags": [
          "WhatsApp"
        ],
        "description": "Crea una campaña de mensajes WhatsApp (inmediata o programada) usando una plantilla aprobada y una fuente de contactos. La fuente puede ser una lista (`contactsSource: \"CONTACT_LIST\"` + `contactListId`), una google-sheet, o un archivo subido previamente.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "campaignName",
                  "templateName",
                  "templateText",
                  "templateParamCount",
                  "contactsSource",
                  "scheduled"
                ],
                "properties": {
                  "campaignName": {
                    "type": "string",
                    "example": "Promoción de navidad"
                  },
                  "templateName": {
                    "type": "string",
                    "example": "bienvenida_v2"
                  },
                  "templateText": {
                    "type": "string",
                    "example": "Hola {{1}}, tu código es {{2}}"
                  },
                  "templateParamCount": {
                    "type": "integer",
                    "example": 2
                  },
                  "contactsSource": {
                    "type": "string",
                    "enum": [
                      "GOOGLE_SHEET",
                      "FILE",
                      "CONTACT_LIST"
                    ]
                  },
                  "contactListId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requerido cuando `contactsSource = CONTACT_LIST`."
                  },
                  "scheduled": {
                    "type": "boolean"
                  },
                  "scheduleDateTime": {
                    "type": "string",
                    "nullable": true,
                    "description": "ISO 8601 con timezone. Requerido cuando `scheduled = true`.",
                    "example": "2026-12-25T14:00:00-03:00"
                  },
                  "mediaUrl": {
                    "type": "string",
                    "nullable": true,
                    "description": "URL devuelta por `POST /campaign-media` cuando la plantilla tiene header de media."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Campaña creada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppCampaign"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns/report": {
      "get": {
        "summary": "Reporte de campañas",
        "operationId": "getWhatsAppCampaignReport",
        "tags": [
          "WhatsApp"
        ],
        "description": "Lista y métricas agregadas de campañas creadas en el rango de fechas indicado.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-05-31"
          }
        ],
        "responses": {
          "200": {
            "description": "Métricas de campañas"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns/{campaignId}/full": {
      "get": {
        "summary": "Detalle completo de campaña",
        "operationId": "getWhatsAppCampaignFull",
        "tags": [
          "WhatsApp"
        ],
        "description": "Devuelve el detalle de una campaña incluyendo el estado individual (eventos) de cada mensaje enviado.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle completo de la campaña",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsAppCampaignFull"
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns/{campaignId}/simple": {
      "get": {
        "summary": "Detalle agregado de campaña",
        "operationId": "getWhatsAppCampaignSimple",
        "tags": [
          "WhatsApp"
        ],
        "description": "Devuelve un resumen de la campaña con conteos agregados (enviados, entregados, leídos, errores) sin el detalle por mensaje.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resumen de la campaña"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns/{campaignId}/cancel": {
      "put": {
        "summary": "Cancelar campaña",
        "operationId": "cancelWhatsAppCampaign",
        "tags": [
          "WhatsApp"
        ],
        "description": "Cancela una campaña programada (estado pasa a `CANCELLED`). No tiene efecto si la campaña ya empezó a enviar.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "cancellationReason": {
                    "type": "string",
                    "example": "La campaña se creó por error"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campaña cancelada"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaigns/{campaignId}/resend": {
      "put": {
        "summary": "Reintentar mensajes fallidos",
        "operationId": "resendWhatsAppCampaign",
        "tags": [
          "WhatsApp"
        ],
        "description": "Reintenta el envío de los mensajes en estado de error de una campaña.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reintento encolado"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/campaign-media": {
      "post": {
        "summary": "Subir media para campaña",
        "operationId": "uploadWhatsAppCampaignMedia",
        "tags": [
          "WhatsApp"
        ],
        "description": "Sube un archivo de media (imagen, video, documento) para usar en una campaña con plantilla con header de media. Devuelve la `mediaUrl` pública (S3) que se pasa al crear la campaña.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Media subido",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mediaUrl": {
                      "type": "string",
                      "example": "https://bucket.s3.us-east-1.amazonaws.com/campaign-media/abc/file.pdf"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/template-media": {
      "post": {
        "summary": "Subir media para una nueva plantilla",
        "operationId": "uploadWhatsAppTemplateMedia",
        "tags": [
          "WhatsApp"
        ],
        "description": "Sube un archivo de media para usarlo en la creación de una plantilla con header `IMAGE`, `VIDEO` o `DOCUMENT`. El `mediaId` devuelto se incluye en el payload de creación de la plantilla.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "templateType",
                  "file"
                ],
                "properties": {
                  "templateType": {
                    "type": "string",
                    "enum": [
                      "IMAGE",
                      "VIDEO",
                      "DOCUMENT"
                    ]
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Media subido",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mediaId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/messages": {
      "post": {
        "summary": "Enviar plantilla HSM",
        "operationId": "sendWhatsAppMessage",
        "tags": [
          "WhatsApp"
        ],
        "description": "Envía una plantilla HSM por uno de dos modos, según el `to`:\n\n- **`to.phone`**: envío puntual a un teléfono arbitrario (E.164). No requiere que el número sea un Contacto Cliengo. `to.variables` es un array posicional que reemplaza los placeholders `{{1}}`, `{{2}}`, ... de la plantilla.\n- **`to.contacts`**: envío masivo a Contactos Cliengo existentes. Las propiedades referenciadas por la plantilla (`{name}`, `{email}`, etc.) se resuelven desde el contacto.\n\n`to.phone` y `to.contacts` son **mutuamente excluyentes**.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "templateId",
                  "to"
                ],
                "properties": {
                  "templateId": {
                    "type": "integer",
                    "description": "ID interno de la plantilla aprobada (no el nombre).",
                    "example": 1
                  },
                  "to": {
                    "description": "Destinatario(s). `to.phone` y `to.contacts` son mutuamente excluyentes — el schema lo expresa con `oneOf`.",
                    "oneOf": [
                      {
                        "type": "object",
                        "title": "Envío a un teléfono arbitrario",
                        "required": [
                          "phone"
                        ],
                        "properties": {
                          "phone": {
                            "type": "string",
                            "description": "Teléfono destino en E.164 (con `+`). No requiere que el número sea un Contacto Cliengo.",
                            "example": "+5491133261336"
                          },
                          "variables": {
                            "type": "array",
                            "description": "Valores posicionales que reemplazan los placeholders `{{1}}`, `{{2}}`, ... de la plantilla.",
                            "items": {
                              "type": "string"
                            },
                            "example": [
                              "Mariano",
                              "123456"
                            ]
                          },
                          "languageCode": {
                            "type": "string",
                            "description": "Override del locale del template (e.g. `es`, `en_US`, `es_AR`). Solo necesario cuando el template tiene un `languageCode` no persistido en hsm-backend (templates legacy). Por defecto se usa el `languageCode` propagado desde Meta/Gupshup; si tampoco existe, fallback `es`.\n",
                            "example": "en_US"
                          }
                        }
                      },
                      {
                        "type": "object",
                        "title": "Envío masivo a Contactos Cliengo",
                        "required": [
                          "contacts"
                        ],
                        "properties": {
                          "contacts": {
                            "type": "array",
                            "minItems": 1,
                            "description": "Contactos Cliengo. Cada item debe traer al menos `id` y `phone`; las props referenciadas en la plantilla (`{name}`, `{email}`, etc.) se resuelven desde el contacto.",
                            "items": {
                              "type": "object",
                              "required": [
                                "id",
                                "phone"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "phone": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "email": {
                                  "type": "string"
                                }
                              }
                            }
                          },
                          "languageCode": {
                            "type": "string",
                            "description": "Mismo override que el modo `phone`, aplicado al template para todos los contactos del envío.",
                            "example": "en_US"
                          }
                        }
                      }
                    ]
                  },
                  "media": {
                    "type": "object",
                    "description": "Media opcional para plantillas con header de imagen/video/documento.",
                    "properties": {
                      "link": {
                        "type": "string",
                        "format": "uri"
                      },
                      "filename": {
                        "type": "string"
                      }
                    }
                  },
                  "location": {
                    "type": "object",
                    "description": "Ubicación opcional para plantillas con header de location.",
                    "properties": {
                      "latitude": {
                        "type": "string",
                        "example": "-34.6037"
                      },
                      "longitude": {
                        "type": "string",
                        "example": "-58.3816"
                      }
                    }
                  }
                }
              },
              "examples": {
                "singlePhone": {
                  "summary": "Envío puntual a un teléfono",
                  "value": {
                    "templateId": 1,
                    "to": {
                      "phone": "+5491133261336",
                      "variables": [
                        "Mariano",
                        "123456"
                      ]
                    }
                  }
                },
                "bulkContacts": {
                  "summary": "Envío masivo a Contactos Cliengo",
                  "value": {
                    "templateId": 1,
                    "to": {
                      "contacts": [
                        {
                          "id": "642c67a495de1100233eb66a",
                          "phone": "+5491133261336",
                          "name": "Mariano",
                          "email": "mariano@example.com"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mensajes encolados"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/events": {
      "get": {
        "summary": "Historial de eventos HSM",
        "operationId": "listWhatsAppEvents",
        "tags": [
          "WhatsApp"
        ],
        "description": "Devuelve el historial de eventos (envío, entrega, lectura, error, respuesta) de los mensajes HSM del canal. Filtros por tipo de evento y rango de fechas.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "enqueque",
                "sent",
                "delivered",
                "read",
                "answered",
                "failed",
                "pending",
                "invalid"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de eventos"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/blacklist": {
      "get": {
        "summary": "Lista de números bloqueados",
        "operationId": "listWhatsAppBlacklist",
        "tags": [
          "WhatsApp"
        ],
        "description": "Devuelve los números de teléfono bloqueados (opt-out) para el canal. Estos números no reciben envíos automáticos.\n",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de números bloqueados"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/contact-lists": {
      "get": {
        "summary": "Listar listas de contactos",
        "operationId": "listWhatsAppContactLists",
        "tags": [
          "WhatsApp"
        ],
        "description": "Listas de contactos creadas para este canal, usadas como destinatarios de campañas.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de contact-lists"
          }
        }
      },
      "post": {
        "summary": "Crear lista de contactos",
        "operationId": "createWhatsAppContactList",
        "tags": [
          "WhatsApp"
        ],
        "description": "Crea una lista de contactos desde un archivo spreadsheet para campañas WhatsApp.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lista de contactos creada"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/account/limit": {
      "get": {
        "summary": "Límite diario de WhatsApp",
        "operationId": "getWhatsAppDailyLimit",
        "tags": [
          "WhatsApp"
        ],
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Límite diario de la línea WhatsApp"
          }
        }
      }
    },
    "/v1/whatsapp/{channelId}/whatsapp-config": {
      "get": {
        "summary": "Configuración WhatsApp del canal",
        "operationId": "getWhatsAppConfig",
        "tags": [
          "WhatsApp"
        ],
        "description": "Balance, uso y detalles de la línea WhatsApp.",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuración WhatsApp"
          }
        }
      }
    },
    "/v1/teams": {
      "get": {
        "summary": "Listar equipos",
        "operationId": "listTeams",
        "tags": [
          "Teams"
        ],
        "responses": {
          "200": {
            "description": "Lista de equipos"
          }
        }
      },
      "post": {
        "summary": "Crear equipo",
        "operationId": "createTeam",
        "tags": [
          "Teams"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "members": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Equipo creado"
          }
        }
      }
    },
    "/v1/teams/{teamId}": {
      "get": {
        "summary": "Obtener equipo",
        "operationId": "getTeam",
        "tags": [
          "Teams"
        ],
        "parameters": [
          {
            "name": "teamId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle del equipo"
          }
        }
      },
      "patch": {
        "summary": "Actualizar equipo",
        "operationId": "patchTeam",
        "tags": [
          "Teams"
        ],
        "parameters": [
          {
            "name": "teamId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "members": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Equipo actualizado"
          }
        }
      },
      "delete": {
        "summary": "Eliminar equipo",
        "operationId": "deleteTeam",
        "tags": [
          "Teams"
        ],
        "parameters": [
          {
            "name": "teamId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Equipo eliminado"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "summary": "Listar webhooks",
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "description": "Devuelve todos los webhooks configurados para la empresa, ordenados por fecha de creación (más recientes primero).\nOpcionalmente filtrá por `websiteId` para ver solo los webhooks de un canal específico.\n",
        "parameters": [
          {
            "name": "websiteId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar webhooks por canal. Si se omite, devuelve todos."
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookSubscription"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crear webhook",
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Crea una nueva suscripción de webhook. Cliengo enviará un `POST` a la URL indicada cada vez que ocurra\nuno de los eventos seleccionados. El webhook se crea activo por defecto y se le asigna un `secret`\nque se enviará en el header `X-Webhook-Secret` de cada entrega para verificar autenticidad.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos (URL vacía, evento desconocido, etc.)"
          }
        }
      }
    },
    "/v1/webhooks/{webhookId}": {
      "get": {
        "summary": "Obtener webhook",
        "operationId": "getWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Devuelve los detalles de un webhook específico.",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          }
        ],
        "responses": {
          "200": {
            "description": "Detalle del webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      },
      "put": {
        "summary": "Actualizar webhook",
        "operationId": "updateWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Actualiza la configuración de un webhook existente. Solo se modifican los campos enviados en el body;\nlos demás se mantienen sin cambios.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos"
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      },
      "patch": {
        "summary": "Activar o desactivar webhook",
        "operationId": "toggleWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Activa o desactiva un webhook sin eliminarlo. Un webhook desactivado no recibe entregas\npero mantiene su configuración y logs.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "isActive"
                ],
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "`true` para activar, `false` para desactivar"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estado actualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      },
      "delete": {
        "summary": "Eliminar webhook",
        "operationId": "deleteWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Elimina un webhook y todo su historial de entregas de forma permanente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          }
        ],
        "responses": {
          "204": {
            "description": "Webhook eliminado"
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      }
    },
    "/v1/webhooks/{webhookId}/logs": {
      "get": {
        "summary": "Historial de entregas",
        "operationId": "getWebhookLogs",
        "tags": [
          "Webhooks"
        ],
        "description": "Devuelve el historial de entregas (delivery log) de un webhook. Cada entrada registra\nel resultado de un intento de entrega: URL, evento, payload enviado, status HTTP de respuesta,\ny si fue exitoso o no. Útil para debugging.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Cantidad de registros a saltar (paginación)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 100
            },
            "description": "Cantidad máxima de registros a devolver"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de entregas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDeliveryLog"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      }
    },
    "/v1/webhooks/ping": {
      "post": {
        "summary": "Probar conectividad",
        "operationId": "pingWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Envía un POST de prueba a una URL para verificar que es accesible antes de crear un webhook.\nNo requiere que el webhook exista. Timeout: 10 segundos.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://tu-servidor.com/webhook"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado de la prueba",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "integer",
                      "description": "HTTP status code de la respuesta (solo si exitoso)"
                    },
                    "error": {
                      "type": "string",
                      "description": "Mensaje de error (solo si falló)"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "status": 200
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{webhookId}/test": {
      "post": {
        "summary": "Enviar evento de prueba",
        "operationId": "testWebhook",
        "tags": [
          "Webhooks"
        ],
        "description": "Envía un evento de prueba real al webhook. El payload incluye `\"test\": true` para que\ntu servidor pueda distinguirlo de eventos reales. La entrega se registra en el log.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/webhookId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "eventType"
                ],
                "properties": {
                  "eventType": {
                    "$ref": "#/components/schemas/WebhookEventType"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado del envío",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Test event delivered (200)"
                }
              }
            }
          },
          "404": {
            "description": "Webhook no encontrado"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "System",
      "description": "Estado del gateway"
    },
    {
      "name": "Accounts",
      "description": "Información y configuración de la cuenta"
    },
    {
      "name": "Channels",
      "description": "Canales configurados"
    },
    {
      "name": "Chatbots",
      "description": "Configuración de chatbots y triggers"
    },
    {
      "name": "Contacts",
      "description": "Buscar y gestionar contactos (Elasticsearch)"
    },
    {
      "name": "Conversations",
      "description": "Conversaciones multicanal (Web, WhatsApp, Facebook, Instagram)"
    },
    {
      "name": "Phases",
      "description": "Fases del pipeline de conversaciones"
    },
    {
      "name": "Plans",
      "description": "Planes de suscripción"
    },
    {
      "name": "Tags",
      "description": "Tags de operador para clasificar conversaciones"
    },
    {
      "name": "Teams",
      "description": "Equipos de operadores"
    },
    {
      "name": "Users",
      "description": "Usuarios y roles de la empresa"
    },
    {
      "name": "Webhooks",
      "description": "Suscribite a eventos en tiempo real. Cliengo envía un `POST` a tu URL cada vez que ocurre\nun evento en tus conversaciones o contactos. Los webhooks incluyen reintentos automáticos\ncon backoff exponencial, headers de seguridad, y un log de entregas para debugging.\n\n**[Ver guia completa de Webhooks →](guides.html#webhooks)** — setup, eventos, payload, seguridad y buenas practicas.\n"
    },
    {
      "name": "WhatsApp",
      "description": "Plantillas y campañas de WhatsApp"
    }
  ]
}
