{
  "openapi": "3.1.0",
  "info": {
    "description": "API pública del motor para apps cliente. Autenticación con `Authorization: Bearer TU_API_KEY` (una key `mw_live_…` de tu app) y permisos por scope. Este documento sale del contrato real del motor, filtrado a las rutas `/v1`.",
    "title": "Motor WhatsApp · API v1",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://motor.ejemplo.com",
      "description": "Reemplaza por la dirección privada de tu motor"
    }
  ],
  "tags": [
    {
      "name": "Apps cliente",
      "description": "Quién hace la request (la app y la key) y qué ofrece el motor: contrato, proveedores, capacidades y scopes."
    },
    {
      "name": "Instancias",
      "description": "Una instancia es un número de WhatsApp vinculado al motor. Créala, vincúlala (QR, código o passkey), configúrala, diagnostícala, mándale comandos de control, elige su proxy y archívala. Aquí también se consulta un comando."
    },
    {
      "name": "Mensajes",
      "description": "Enviar por el outbox durable (texto, multimedia, ubicación, contactos, reacciones, ediciones, encuestas, interactivos), leer el store del motor, receipts, encuestas, respuestas a interactivos, presencia y cancelar un comando en cola."
    },
    {
      "name": "Multimedia",
      "description": "Subir archivos privados para enviarlos y descargar los recibidos, con permisos temporales."
    },
    {
      "name": "Eventos",
      "description": "El ledger de eventos de cada instancia (secuencia `seq` sin huecos) y los streams en vivo por SSE y WebSocket, con cursor para reanudar."
    },
    {
      "name": "Webhooks",
      "description": "Suscripciones de webhooks firmados con HMAC-SHA256, sus entregas e intentos, la rotación del secreto, la prueba del destino y el replay de eventos ya aceptados."
    },
    {
      "name": "Chats",
      "description": "El estado de los chats en WhatsApp (fijado, archivado, silenciado, no leído) y sus acciones por el appstate."
    },
    {
      "name": "Etiquetas",
      "description": "Las etiquetas de WhatsApp (Business) o las Listas del número: crearlas, editarlas, eliminarlas y asociarlas."
    },
    {
      "name": "Contactos",
      "description": "Los contactos de transporte del número, la resolución de identidades (LID y teléfono), las consultas al servidor con cuota diaria y los bloqueos."
    },
    {
      "name": "Grupos",
      "description": "Crear y administrar grupos: participantes, ajustes, nombre, descripción, foto, invitaciones y solicitudes."
    },
    {
      "name": "Comunidades",
      "description": "Crear comunidades y vincular o desvincular sus grupos."
    },
    {
      "name": "Canales",
      "description": "Canales (newsletters) de WhatsApp: crear, seguir, silenciar, ver publicaciones, vistas y reacciones."
    },
    {
      "name": "Status",
      "description": "Los status (stories) recibidos y publicados mientras se retienen, la audiencia y la publicación (experimental)."
    },
    {
      "name": "Llamadas",
      "description": "Las llamadas entrantes y su rechazo. El motor no atiende voz ni vídeo."
    },
    {
      "name": "Perfil y privacidad",
      "description": "El perfil propio del número (nombre, recado, foto) y su privacidad."
    },
    {
      "name": "Comercio",
      "description": "El catálogo y las colecciones de WhatsApp Business, con su cuota comercial."
    },
    {
      "name": "Historial",
      "description": "La política del historial, pedidos e importaciones de mensajes viejos y sus trabajos."
    },
    {
      "name": "Catálogo de eventos",
      "description": "Un webhook por tipo de evento: el sobre común (`schema_version`, `event_id`, `instance_id`, `seq`, `type`…), el `data` de cada tipo y los encabezados `X-MW-…` de la firma. El mismo sobre llega por la API de eventos y por los streams."
    }
  ],
  "paths": {
    "/v1/capabilities": {
      "get": {
        "description": "El contrato de la API, la negociación del contrato de eventos (versiones, transportes, cursor, límites de streams), los proveedores con su versión, las capacidades del transporte (las experimentales dicen que no están garantizadas) y los scopes de tu key. Consúltalo al arrancar tu integración para saber qué puedes usar.\n\n**Scope:** ninguno: sirve cualquier key válida.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).",
        "operationId": "capabilities",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "avisos": {},
                  "capacidades": [
                    {
                      "clave": "texto",
                      "estado": "disponible",
                      "etapa": "texto"
                    }
                  ],
                  "contrato": "1.0.0",
                  "eventos": {
                    "conexiones_por_app": 1,
                    "cursor": "CURSOR_OPACO",
                    "dias_reanudacion": 1,
                    "keepalive_segundos": 1,
                    "schema_versions": [
                      1
                    ],
                    "transportes": [
                      "webhook",
                      "sse",
                      "websocket"
                    ],
                    "version": "1",
                    "versiones_soportadas": [
                      "1"
                    ]
                  },
                  "proveedores": [
                    {
                      "disponible": false,
                      "nombre": "whatsmeow",
                      "version": "texto"
                    }
                  ],
                  "scopes": [
                    "texto"
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Contrato, proveedores y capacidades",
        "tags": [
          "Apps cliente"
        ]
      }
    },
    "/v1/commands/{id}": {
      "get": {
        "description": "El scope del tipo del comando. `status`: aceptado, en_cola, ejecutando, completado (control), enviado (mensaje: lo aceptó el servidor), fallido (con `error_code` y `stage`; si WhatsApp lo rechazó con un código, `server_code` y `server_origin`), ambiguo (pudo salir; nunca se reenvía) o cancelado. Un envío trae su `provider_message_id` fijo y `next_try` mientras espera.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-comando",
        "parameters": [
          {
            "description": "ID del comando.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID del comando.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "en_cola",
                  "type": "message.text",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Consultar un comando",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/commands/{id}/cancel": {
      "post": {
        "description": "El scope del tipo del comando. Solo si sigue `aceptado` o `en_cola`; si ya entró al envío (`ejecutando`, `enviado`, `ambiguo`) o terminó, 409: ya puede tener efecto externo. Repetir la cancelación devuelve el mismo comando.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: el comando ya entró al envío o terminó: puede tener efecto externo.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cancelar-comando",
        "parameters": [
          {
            "description": "ID del comando.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID del comando.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "en_cola",
                  "type": "message.text",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cancelar un comando que todavía no se ejecutó",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/deliveries": {
      "get": {
        "description": "Scope `events:read`. Las entregas de tu app, de la más nueva a la más vieja: estado, intentos, próximo intento, último status y error saneado (un código, nunca la URL ni un cuerpo).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-entregas",
        "parameters": [
          {
            "description": "Estados separados por coma: pendiente, entregada, fallida.",
            "explode": false,
            "in": "query",
            "name": "estado",
            "schema": {
              "description": "Estados separados por coma: pendiente, entregada, fallida.",
              "examples": [
                "pendiente,fallida"
              ],
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "suscripcion_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "instancia_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "pagina",
            "schema": {
              "default": 1,
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "por_pagina",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "elementos": [
                    {
                      "creada_en": "2026-10-24T15:08:12Z",
                      "delivery_id": "8a1d2c3e-0000-4000-8000-0000f79655c3",
                      "estado": "pendiente",
                      "event_id": "8a1d2c3e-0000-4000-8000-0000a08b063d",
                      "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                      "instancia": "texto",
                      "intentos": 1,
                      "seq": 1187,
                      "suscripcion": "texto",
                      "suscripcion_id": "8a1d2c3e-0000-4000-8000-0000505170bd",
                      "type": "message.received"
                    }
                  ],
                  "pagina": 1,
                  "por_pagina": 50,
                  "total": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/ListaEntregasOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Listar entregas",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/deliveries/{id}": {
      "get": {
        "description": "Una entrega de webhook (un evento hacia una suscripción) con su estado, su próximo intento y cada intento hecho: momento, status HTTP, duración y error saneado (un código, nunca la URL ni un cuerpo).\n\nScope `events:read`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-entrega",
        "parameters": [
          {
            "description": "ID de la entrega (delivery_id).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la entrega (delivery_id).",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "creada_en": "2026-10-24T15:08:12Z",
                  "delivery_id": "8a1d2c3e-0000-4000-8000-0000f79655c3",
                  "estado": "pendiente",
                  "event_id": "8a1d2c3e-0000-4000-8000-0000a08b063d",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "instancia": "texto",
                  "intentos": 1,
                  "seq": 1187,
                  "suscripcion": "texto",
                  "suscripcion_id": "8a1d2c3e-0000-4000-8000-0000505170bd",
                  "type": "message.received"
                },
                "schema": {
                  "$ref": "#/components/schemas/VistaEntrega"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Ver una entrega y sus intentos",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/events/stream": {
      "get": {
        "description": "Scope `events:read`. Los eventos del ledger en vivo, con el mismo envelope que la API de eventos y los webhooks (y la misma redacción por retención). **Sin cursor**, empieza en lo que llegue desde ahora (la trama `listo` trae el cursor de partida). **Para reanudar**, manda el último cursor recibido en `Last-Event-ID` (SSE lo hace solo) o en `?desde=`: reanudar no salta ni repite un evento. Un cursor de otra app es 403; uno alterado, 422; uno con eventos sin leer más viejos que la retención (Ajustes → Streams) es **410** con `primer_cursor` (usarlo es aceptar el salto: nunca se salta en silencio). El orden es el de `seq` dentro de cada instancia; entre instancias, por llegada. El motor corta el stream con una trama `cierre` (su `motivo`, si es `reanudable` y el `cursor`): `credencial_revocada` (key revocada o vencida, o la app suspendida), `sin_scope`, `apagado` (el motor se reinicia: reanuda con el cursor), `cortado_por_operador` o `error_interno`. **Un `cliente_lento`** (el cliente no lee y su buffer quedó lleno) **se corta sin trama**: SSE cierra la conexión y WebSocket la corta sin close frame. Reconecta con el último cursor que recibiste; el motivo queda en `GET /v1/events/streams`. Hay un tope de streams abiertos por app (429).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "stream-eventos",
        "parameters": [
          {
            "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
            "explode": false,
            "in": "query",
            "name": "desde",
            "schema": {
              "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
            "in": "header",
            "name": "Last-Event-ID",
            "schema": {
              "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "Tipos separados por coma (vacío: todos).",
            "explode": false,
            "in": "query",
            "name": "types",
            "schema": {
              "description": "Tipos separados por coma (vacío: todos).",
              "examples": [
                "message.received,receipt"
              ],
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
            "explode": false,
            "in": "query",
            "name": "contrato",
            "schema": {
              "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
              "examples": [
                "1"
              ],
              "maxLength": 16,
              "type": "string"
            }
          },
          {
            "description": "IDs de instancia separados por coma (vacío: todas las que alcanza la key).",
            "explode": false,
            "in": "query",
            "name": "instances",
            "schema": {
              "description": "IDs de instancia separados por coma (vacío: todas las que alcanza la key).",
              "maxLength": 4000,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "`text/event-stream`: `event: listo` (con el cursor de partida), `event: evento` (con `id:` = su cursor y el envelope en `data:`), comentarios de keepalive y `event: cierre` con el motivo (un `cliente_lento` se corta sin ella)."
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Stream de eventos de la app (SSE)",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/events/streams": {
      "get": {
        "description": "Scope `events:read`. Los streams de tu app abiertos en este proceso del motor, con su posición y su atraso por instancia, y los últimos cierres con su motivo. Una key restringida a ciertas instancias solo ve los streams (abiertos o cerrados) que cubren únicamente instancias de su alcance; un stream que cubre también otras, o toda la app, no se muestra.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.",
        "operationId": "streams-abiertos",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "abiertos": [
                    {
                      "abierto_en": "2026-10-24T15:08:12Z",
                      "atraso": 1,
                      "buffer_bytes": 48213,
                      "buffer_limite": 1,
                      "bytes_enviados": 1,
                      "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                      "cliente_nombre": "Ventas Centro",
                      "estado": "al_dia",
                      "eventos_enviados": 1,
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "instancias": [
                        {
                          "atraso": 1,
                          "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                          "seq": 1187,
                          "ultimo_seq": 1187
                        }
                      ],
                      "instancias_filtro": [
                        "texto"
                      ],
                      "key_prefijo": "texto",
                      "tipos": [
                        "message.received"
                      ],
                      "transporte": "sse"
                    }
                  ],
                  "cierres": [
                    {
                      "abierto_en": "2026-10-24T15:08:12Z",
                      "cerrado_en": "2026-10-24T15:08:12Z",
                      "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                      "cliente_nombre": "Ventas Centro",
                      "eventos_enviados": 1,
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "key_prefijo": "texto",
                      "motivo": "credencial_revocada",
                      "transporte": "sse"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/StreamsOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los streams abiertos de la app",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/events/ws": {
      "get": {
        "description": "Scope `events:read`. Los eventos del ledger en vivo, con el mismo envelope que la API de eventos y los webhooks (y la misma redacción por retención). **Sin cursor**, empieza en lo que llegue desde ahora (la trama `listo` trae el cursor de partida). **Para reanudar**, manda el último cursor recibido en `Last-Event-ID` (SSE lo hace solo) o en `?desde=`: reanudar no salta ni repite un evento. Un cursor de otra app es 403; uno alterado, 422; uno con eventos sin leer más viejos que la retención (Ajustes → Streams) es **410** con `primer_cursor` (usarlo es aceptar el salto: nunca se salta en silencio). El orden es el de `seq` dentro de cada instancia; entre instancias, por llegada. El motor corta el stream con una trama `cierre` (su `motivo`, si es `reanudable` y el `cursor`): `credencial_revocada` (key revocada o vencida, o la app suspendida), `sin_scope`, `apagado` (el motor se reinicia: reanuda con el cursor), `cortado_por_operador` o `error_interno`. **Un `cliente_lento`** (el cliente no lee y su buffer quedó lleno) **se corta sin trama**: SSE cierra la conexión y WebSocket la corta sin close frame. Reconecta con el último cursor que recibiste; el motivo queda en `GET /v1/events/streams`. Hay un tope de streams abiertos por app (429). La key va en `Authorization: Bearer` del handshake.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "stream-eventos-ws",
        "parameters": [
          {
            "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
            "explode": false,
            "in": "query",
            "name": "desde",
            "schema": {
              "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
            "in": "header",
            "name": "Last-Event-ID",
            "schema": {
              "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "Tipos separados por coma (vacío: todos).",
            "explode": false,
            "in": "query",
            "name": "types",
            "schema": {
              "description": "Tipos separados por coma (vacío: todos).",
              "examples": [
                "message.received,receipt"
              ],
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
            "explode": false,
            "in": "query",
            "name": "contrato",
            "schema": {
              "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
              "examples": [
                "1"
              ],
              "maxLength": 16,
              "type": "string"
            }
          },
          {
            "description": "IDs de instancia separados por coma (vacío: todas las que alcanza la key).",
            "explode": false,
            "in": "query",
            "name": "instances",
            "schema": {
              "description": "IDs de instancia separados por coma (vacío: todas las que alcanza la key).",
              "maxLength": 4000,
              "type": "string"
            }
          }
        ],
        "responses": {
          "101": {
            "description": "Cambia a WebSocket. Mensajes JSON de texto: `{\"tipo\":\"listo\",\"id\":<cursor>,\"listo\":{…}}`, `{\"tipo\":\"evento\",\"id\":<cursor>,\"evento\":<envelope>}`, `{\"tipo\":\"keepalive\"}` y `{\"tipo\":\"cierre\",\"cierre\":{\"motivo\",\"reanudable\",\"cursor\"}}`; el close frame lleva el motivo. Un `cliente_lento` se corta sin trama `cierre` ni close frame."
          },
          "200": {
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Stream de eventos de la app (WebSocket)",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/instances": {
      "get": {
        "description": "Las instancias paginadas (`pagina`, `por_pagina`) con su estado y su configuración.\n\nScope `instances:read`. Solo las de tu app (y las de tu key, si está restringida).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-instancias",
        "parameters": [
          {
            "explode": false,
            "in": "query",
            "name": "pagina",
            "schema": {
              "default": 1,
              "format": "int64",
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "10, 20, 50 o 100.",
            "explode": false,
            "in": "query",
            "name": "por_pagina",
            "schema": {
              "default": 20,
              "description": "10, 20, 50 o 100.",
              "format": "int64",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "elementos": [
                    {
                      "actualizada_en": "2026-10-24T15:08:12Z",
                      "archivada_en": "2026-10-24T15:08:12Z",
                      "bloqueada_hasta": "2026-10-24T15:08:12Z",
                      "caida_desde": "2026-10-24T15:08:12Z",
                      "canario": false,
                      "checked_at": "2026-10-24T15:08:12Z",
                      "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                      "conectada_en": "2026-10-24T15:08:12Z",
                      "config": {
                        "reconexion_automatica": false
                      },
                      "creada_en": "2026-10-24T15:08:12Z",
                      "estado": "conectado",
                      "estado_deseado": "activo",
                      "generacion": 1,
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "motivo": "",
                      "nombre": "Ventas Centro",
                      "numero": "+NUMERO_DE_TU_TELEFONO",
                      "owner_ref": "empresa-42",
                      "proveedor": "whatsmeow",
                      "proximo_intento_en": "2026-10-24T15:08:12Z",
                      "proxy_id": "8a1d2c3e-0000-4000-8000-0000c9e41541",
                      "reconexiones": 1,
                      "ultimo_error": "",
                      "ultimo_error_en": "2026-10-24T15:08:12Z",
                      "version": 1,
                      "vinculada_en": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "pagina": 1,
                  "por_pagina": 50,
                  "total": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/ListaInstanciasV1OutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Listar instancias",
        "tags": [
          "Instancias"
        ]
      },
      "post": {
        "description": "Scope `instances:create`. La app sale de la API key. Respeta el cupo de la app (429). Con `Idempotency-Key`, repetir la misma petición devuelve la misma instancia (200); la misma clave con otros datos, 409.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `409`: la `Idempotency-Key` ya se usó con otros datos, o la app está suspendida.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: la app llegó a su cupo de instancias.",
        "operationId": "crear-instancia",
        "parameters": [
          {
            "description": "Opcional. Hace el alta idempotente.",
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "description": "Opcional. Hace el alta idempotente.",
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "nombre": "Ventas Centro",
                "owner_ref": "empresa-42"
              },
              "schema": {
                "$ref": "#/components/schemas/Crear-instanciaRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "archivada_en": "2026-10-24T15:08:12Z",
                  "bloqueada_hasta": "2026-10-24T15:08:12Z",
                  "caida_desde": "2026-10-24T15:08:12Z",
                  "canario": false,
                  "checked_at": "2026-10-24T15:08:12Z",
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "conectada_en": "2026-10-24T15:08:12Z",
                  "config": {
                    "reconexion_automatica": false
                  },
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "conectado",
                  "estado_deseado": "activo",
                  "generacion": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "motivo": "",
                  "nombre": "Ventas Centro",
                  "numero": "+NUMERO_DE_TU_TELEFONO",
                  "owner_ref": "empresa-42",
                  "proveedor": "whatsmeow",
                  "proximo_intento_en": "2026-10-24T15:08:12Z",
                  "proxy_id": "8a1d2c3e-0000-4000-8000-0000c9e41541",
                  "reconexiones": 1,
                  "ultimo_error": "",
                  "ultimo_error_en": "2026-10-24T15:08:12Z",
                  "version": 1,
                  "vinculada_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Instancia"
                }
              }
            },
            "description": "Created"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:create.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear una instancia",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}": {
      "delete": {
        "description": "Scope `instances:logout`. Es el comando `instance.archive`: 202 con el comando. Desvincula el número (Logout si la sesión está autenticada; si no, borra las claves locales), borra la sesión del store de forma idempotente y deja la instancia `archivado`. **Nunca borra eventos del ledger**: lo aceptado y no entregado se conserva. Repetirlo no hace daño. La instancia archivada deja de contar para el cupo.\n\n**Asíncrona:** es el comando `instance.archive`: responde `202` con el comando; sigue su estado en `GET /v1/commands/{id}`. La instancia pasa a `archivado` y llega `state.changed`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "archivar-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Opcional.",
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "description": "Opcional.",
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "instance.archive",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:logout.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Archivar una instancia (desvincula y borra la sesión)",
        "tags": [
          "Instancias"
        ]
      },
      "get": {
        "description": "La instancia con su estado conciliado, su generación, su configuración propia y su `version` (para el `version_esperada` de `PATCH`). Una instancia de otra app, o fuera del alcance de tu key, es 404.\n\nScope `instances:read`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "archivada_en": "2026-10-24T15:08:12Z",
                  "bloqueada_hasta": "2026-10-24T15:08:12Z",
                  "caida_desde": "2026-10-24T15:08:12Z",
                  "canario": false,
                  "checked_at": "2026-10-24T15:08:12Z",
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "conectada_en": "2026-10-24T15:08:12Z",
                  "config": {
                    "reconexion_automatica": false
                  },
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "conectado",
                  "estado_deseado": "activo",
                  "generacion": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "motivo": "",
                  "nombre": "Ventas Centro",
                  "numero": "+NUMERO_DE_TU_TELEFONO",
                  "owner_ref": "empresa-42",
                  "proveedor": "whatsmeow",
                  "proximo_intento_en": "2026-10-24T15:08:12Z",
                  "proxy_id": "8a1d2c3e-0000-4000-8000-0000c9e41541",
                  "reconexiones": 1,
                  "ultimo_error": "",
                  "ultimo_error_en": "2026-10-24T15:08:12Z",
                  "version": 1,
                  "vinculada_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Instancia"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Ver una instancia",
        "tags": [
          "Instancias"
        ]
      },
      "patch": {
        "description": "Scope `instances:manage`. Configuración propia validada (campos cerrados: un campo de más es 422). `version` sube con cada cambio de nombre, configuración o estado deseado (no con las caídas de red): con `version_esperada` vieja, 409.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: `version_esperada` no coincide: la instancia cambió desde que la leíste.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "actualizar-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "config": {
                  "mensajes_por_segundo": 2,
                  "rafaga": 5,
                  "rechazar_llamadas": true
                },
                "nombre": "Ventas Centro",
                "version_esperada": 3
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "archivada_en": "2026-10-24T15:08:12Z",
                  "bloqueada_hasta": "2026-10-24T15:08:12Z",
                  "caida_desde": "2026-10-24T15:08:12Z",
                  "canario": false,
                  "checked_at": "2026-10-24T15:08:12Z",
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "conectada_en": "2026-10-24T15:08:12Z",
                  "config": {
                    "reconexion_automatica": false
                  },
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "conectado",
                  "estado_deseado": "activo",
                  "generacion": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "motivo": "",
                  "nombre": "Ventas Centro",
                  "numero": "+NUMERO_DE_TU_TELEFONO",
                  "owner_ref": "empresa-42",
                  "proveedor": "whatsmeow",
                  "proximo_intento_en": "2026-10-24T15:08:12Z",
                  "proxy_id": "8a1d2c3e-0000-4000-8000-0000c9e41541",
                  "reconexiones": 1,
                  "ultimo_error": "",
                  "ultimo_error_en": "2026-10-24T15:08:12Z",
                  "version": 1,
                  "vinculada_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Instancia"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar el nombre o la configuración de una instancia",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/appstate": {
      "get": {
        "description": "Scope `chats:read`. Cada colección (regular: etiquetas; regular_low: fijar, archivar, leído; regular_high: silenciar, destacar, borrar) con su versión, el último fullSync, el error tipificado con su próximo intento y si falta una clave del appstate (el motor la reintenta y, si no llega, le pide una copia al teléfono).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "sincronizacion-appstate",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "colecciones": [
                    {
                      "coleccion": "regular",
                      "estado": "pendiente",
                      "reintentos": 1,
                      "requiere_full": false,
                      "version": 1
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/AppstateOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope chats:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La sincronización del appstate",
        "tags": [
          "Chats"
        ]
      }
    },
    "/v1/instances/{id}/appstate/resync": {
      "post": {
        "description": "Scope `chats:manage`. Un comando durable (`appstate.resync`): marca las colecciones y las vuelve a traer completas. Repetirlo no duplica nada (la proyección es «última escritura gana»).\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `appstate.sync` (y un `appstate.changed` por cada cambio que traiga), con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "resincronizar-appstate",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "colecciones": [
                  "regular_low"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoResync"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "appstate.resync",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope chats:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Pedir un fullSync del appstate",
        "tags": [
          "Chats"
        ]
      }
    },
    "/v1/instances/{id}/blocklist": {
      "get": {
        "description": "Scope `privacy:read`. Los bloqueados según lo último que dijo WhatsApp (los cambios del teléfono llegan como `blocklist.changed`). Con `actualizar=true` el motor pide la lista antes al servidor.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-bloqueados",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "bloqueados": [
                    {
                      "bloqueado": false,
                      "cambio_en": "2026-10-24T15:08:12Z",
                      "contacto": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "desde": "texto"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/BloqueadosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope privacy:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los contactos bloqueados",
        "tags": [
          "Contactos"
        ]
      },
      "post": {
        "description": "Scope `privacy:write`. `contact.block`: el servidor devuelve la lista completa, que queda confirmada, con `blocklist.changed` (con `command_id`). Un contacto sin LID conocido puede fallar con `sin_identidad`.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `blocklist.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "bloquear-contacto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "bloquear": true,
                "destino": {
                  "telefono": "+NUMERO_DEL_CONTACTO"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoBloqueo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "contact.block",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope privacy:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Bloquear o desbloquear un contacto",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/business/catalog": {
      "get": {
        "description": "Scope `catalog:read` (el perfil comercial sigue en `/business/profile`). Una página remota del catálogo: `limit` productos y, si WhatsApp informó una continuación, `has_more: true` y `next_cursor` (del motor: opaco, firmado y atado a la app, la instancia, el número vinculado, el negocio y el límite; vence según Ajustes y sobrevive a un reinicio). Sin continuación, `has_more` es **null**: que el catálogo terminó no está verificado. Una página con menos productos que el límite puede traer continuación. El precio es el texto exacto de WhatsApp (`precio_proveedor`, `escala_precio: null`) y no hay existencias (`disponibilidad: null`). Un cursor alterado es 422, uno de otra instancia o app 404, uno vencido 409 `cursor_vencido` y uno de otra vinculación o con otro negocio o límite 409 `cursor_incompatible`. Sin `jid` ni `peer_ref`, el del número de la instancia; con otro negocio, lo que ESTE número puede ver de él (el servidor decide). Se consulta en el momento (una instancia sin conexión es 409 `no_conectada`), con la cuota diaria de consultas comerciales de la app (cuenta todo intento que pudo salir, también si falla), una consulta a la vez por instancia y el enfriamiento si WhatsApp limita. Una consulta igual dentro de la frescura de Ajustes devuelve la misma lectura (`origen: cache`, sin gastar cuota). Cada consulta a WhatsApp deja un evento `query.completed` o `query.failed` (sin datos del negocio). **Ningún resultado se inventa**: una lista vacía es la respuesta real del servidor (causa desconocida), y un catálogo que WhatsApp no deja ver (403 `catalogo_no_autorizado`), uno que no encuentra (404 `catalogo_no_disponible`), un error (503) o una espera agotada (504 `consulta_agotada`) son errores distintos; ninguno afirma que el número no es Business. Las URLs de las imágenes son de WhatsApp y temporales. La vía con que se pide (Ajustes, Catálogo comercial) queda en el evento, y un código del servidor en su `server_code`; la vía graphql sin su token es 409 `via_catalogo_sin_token`, sin consultar. Solo lectura.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `501`: no está implementado.\n- `502`: WhatsApp rechazó la consulta o devolvió algo que el motor no puede entregar tal cual.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.\n- `504`: WhatsApp no contestó a tiempo.",
        "operationId": "catalogo-comercial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "JID de usuario del negocio (@s.whatsapp.net, o un @lid con su teléfono ya comprobado por esta instancia).",
            "explode": false,
            "in": "query",
            "name": "jid",
            "schema": {
              "description": "JID de usuario del negocio (@s.whatsapp.net, o un @lid con su teléfono ya comprobado por esta instancia).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de un contacto de esta instancia.",
            "explode": false,
            "in": "query",
            "name": "peer_ref",
            "schema": {
              "description": "El peer_ref de un contacto de esta instancia.",
              "maxLength": 36,
              "type": "string"
            }
          },
          {
            "description": "El next_cursor de la página anterior (del motor: opaco y firmado).",
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "El next_cursor de la página anterior (del motor: opaco y firmado).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "Productos por página (de 1 a 50; 10 si no se indica). Con un cursor, el de su primera página.",
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "description": "Productos por página (de 1 a 50; 10 si no se indica). Con un cursor, el de su primera página.",
              "format": "int64",
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "completitud": "pagina",
                  "consulta_id": "8a1d2c3e-0000-4000-8000-0000242516f2",
                  "consultado_en": "2026-10-24T15:08:12Z",
                  "continuacion": "informada",
                  "cuota": {
                    "cuota": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "fresca_hasta": "2026-10-24T15:08:12Z",
                  "has_more": false,
                  "limit": 50,
                  "negocio_jid": "CONTACTO@s.whatsapp.net",
                  "next_cursor": "CURSOR_OPACO",
                  "origen": "whatsapp",
                  "paginacion": "proveedor",
                  "productos": [
                    {
                      "disponibilidad": "texto",
                      "escala_precio": 1,
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "imagenes": [
                        {}
                      ],
                      "oculto": false
                    }
                  ],
                  "propio": false,
                  "total": 1,
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/CatalogoOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope catalog:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "501": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Implemented"
          },
          "502": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Bad Gateway"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          },
          "504": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gateway Timeout"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Una página del catálogo de un negocio (P055)",
        "tags": [
          "Comercio"
        ]
      }
    },
    "/v1/instances/{id}/business/collections": {
      "get": {
        "description": "Scope `catalog:read`. La vista que da WhatsApp con `collection_limit` colecciones y `item_limit` productos por colección (los dos se piden por separado; su producto, hasta 200). **La continuación remota de las colecciones no está implementada** (el protocolo observado no la tiene): `continuacion_remota: false`, `proveedor_has_more: null`, `completitud: desconocida`, y `posible_truncamiento: true` si la vista alcanzó alguno de los límites. `next_cursor` pagina la vista **guardada** (`paginacion: snapshot_local`, `limit` colecciones por página), sin volver a WhatsApp: no prueba que se descargaron todas. Un producto puede estar en varias colecciones. Sin `jid` ni `peer_ref`, el del número de la instancia; con otro negocio, lo que ESTE número puede ver de él (el servidor decide). Se consulta en el momento (una instancia sin conexión es 409 `no_conectada`), con la cuota diaria de consultas comerciales de la app (cuenta todo intento que pudo salir, también si falla), una consulta a la vez por instancia y el enfriamiento si WhatsApp limita. Una consulta igual dentro de la frescura de Ajustes devuelve la misma lectura (`origen: cache`, sin gastar cuota). Cada consulta a WhatsApp deja un evento `query.completed` o `query.failed` (sin datos del negocio). **Ningún resultado se inventa**: una lista vacía es la respuesta real del servidor (causa desconocida), y un catálogo que WhatsApp no deja ver (403 `catalogo_no_autorizado`), uno que no encuentra (404 `catalogo_no_disponible`), un error (503) o una espera agotada (504 `consulta_agotada`) son errores distintos; ninguno afirma que el número no es Business. Las URLs de las imágenes son de WhatsApp y temporales. La vía con que se pide (Ajustes, Catálogo comercial) queda en el evento, y un código del servidor en su `server_code`; la vía graphql sin su token es 409 `via_catalogo_sin_token`, sin consultar. Solo lectura.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `501`: no está implementado.\n- `502`: WhatsApp rechazó la consulta o devolvió algo que el motor no puede entregar tal cual.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.\n- `504`: WhatsApp no contestó a tiempo.",
        "operationId": "colecciones-comerciales",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "JID de usuario del negocio (@s.whatsapp.net, o un @lid con su teléfono ya comprobado por esta instancia).",
            "explode": false,
            "in": "query",
            "name": "jid",
            "schema": {
              "description": "JID de usuario del negocio (@s.whatsapp.net, o un @lid con su teléfono ya comprobado por esta instancia).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de un contacto de esta instancia.",
            "explode": false,
            "in": "query",
            "name": "peer_ref",
            "schema": {
              "description": "El peer_ref de un contacto de esta instancia.",
              "maxLength": 36,
              "type": "string"
            }
          },
          {
            "description": "El next_cursor de la página anterior (del motor: opaco y firmado).",
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "El next_cursor de la página anterior (del motor: opaco y firmado).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "Colecciones que se piden a WhatsApp (de 1 a 20; 10 si no se indica).",
            "explode": false,
            "in": "query",
            "name": "collection_limit",
            "schema": {
              "description": "Colecciones que se piden a WhatsApp (de 1 a 20; 10 si no se indica).",
              "format": "int64",
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Productos por colección que se piden a WhatsApp (de 1 a 50; 10 si no se indica). collection_limit × item_limit, hasta 200.",
            "explode": false,
            "in": "query",
            "name": "item_limit",
            "schema": {
              "description": "Productos por colección que se piden a WhatsApp (de 1 a 50; 10 si no se indica). collection_limit × item_limit, hasta 200.",
              "format": "int64",
              "maximum": 50,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Colecciones por página de la vista local (de 1 a 20; 10 si no se indica).",
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "description": "Colecciones por página de la vista local (de 1 a 20; 10 si no se indica).",
              "format": "int64",
              "maximum": 20,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "colecciones": [
                    {
                      "alcanza_limite": false,
                      "completitud_productos": "desconocida",
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "productos": [
                        {
                          "disponibilidad": "texto",
                          "escala_precio": 1,
                          "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                          "imagenes": [
                            {}
                          ],
                          "oculto": false
                        }
                      ],
                      "puede_apelar": false
                    }
                  ],
                  "collection_limit": 1,
                  "completitud": "desconocida",
                  "consulta_id": "8a1d2c3e-0000-4000-8000-0000242516f2",
                  "consultado_en": "2026-10-24T15:08:12Z",
                  "continuacion_remota": false,
                  "cuota": {
                    "cuota": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "fresca_hasta": "2026-10-24T15:08:12Z",
                  "has_more": false,
                  "item_limit": 1,
                  "limit": 50,
                  "negocio_jid": "CONTACTO@s.whatsapp.net",
                  "next_cursor": "CURSOR_OPACO",
                  "origen": "whatsapp",
                  "paginacion": "snapshot_local",
                  "paging_recibido": false,
                  "posible_truncamiento": false,
                  "propio": false,
                  "proveedor_has_more": false,
                  "total_vista": 1,
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/ColeccionesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope catalog:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "501": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Implemented"
          },
          "502": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Bad Gateway"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          },
          "504": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gateway Timeout"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Las colecciones del catálogo de un negocio (P056)",
        "tags": [
          "Comercio"
        ]
      }
    },
    "/v1/instances/{id}/business/profile": {
      "get": {
        "description": "Scope `contacts:lookup`. Exactamente uno de `telefono`, `jid` o `peer_ref` (ninguno: el número de la instancia). Devuelve la categoría, la descripción, la dirección, el correo, los sitios y el horario tal cual los entrega WhatsApp. Un número que **no es Business** devuelve `es_negocio: false`, sin campos: es la respuesta real del servidor, no un perfil vacío inventado. Se consulta en el momento (una instancia sin conexión es 409 `no_conectada`) y gasta una consulta de la cuota diaria de la app. El catálogo y las colecciones no van aquí. **No es un oráculo público**: cada número (o perfil) consume una consulta de la cuota diaria de la app (`limites.consultas_identidad_dia`, o la de la app) con un máximo por consulta (`limites.numeros_por_consulta`). Un número inválido (422 con sus posiciones) o la cuota agotada (429 `cuota_agotada` con `Retry-After`) rechazan la consulta entera ANTES de llegar al servidor y sin consumir nada. Sin conexión, 409 `no_conectada`. Una consulta no crea contactos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.",
        "operationId": "perfil-comercial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Número internacional.",
            "explode": false,
            "in": "query",
            "name": "telefono",
            "schema": {
              "description": "Número internacional.",
              "maxLength": 32,
              "type": "string"
            }
          },
          {
            "description": "JID de usuario (@s.whatsapp.net o @lid).",
            "explode": false,
            "in": "query",
            "name": "jid",
            "schema": {
              "description": "JID de usuario (@s.whatsapp.net o @lid).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de un contacto de esta instancia.",
            "explode": false,
            "in": "query",
            "name": "peer_ref",
            "schema": {
              "description": "El peer_ref de un contacto de esta instancia.",
              "maxLength": 36,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "consultado_en": "2026-10-24T15:08:12Z",
                  "cuota": {
                    "cuota": 1,
                    "maximo_por_consulta": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "es_negocio": false,
                  "jid": "CONTACTO@s.whatsapp.net",
                  "propio": false
                },
                "schema": {
                  "$ref": "#/components/schemas/PerfilComercialOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:lookup.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El perfil comercial de un número (GetBusinessProfile)",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/calls": {
      "get": {
        "description": "Scope `calls:manage`. Las llamadas que llegaron y su estado (`entrante`, `aceptada` en otro dispositivo, `terminada`, `rechazada`). Con `entrantes=true`, solo las que siguen sonando. Cada señal llega también como `call.offer`, `call.offer_notice`, `call.preaccept`, `call.accept`, `call.terminate`, `call.reject` o `call.signal`. **El motor no atiende voz ni vídeo.**\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-llamadas",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Solo las que siguen sonando.",
            "explode": false,
            "in": "query",
            "name": "entrantes",
            "schema": {
              "description": "Solo las que siguen sonando.",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "llamadas": [
                    {
                      "actualizada_en": "2026-10-24T15:08:12Z",
                      "call_id": "CALL_ID",
                      "de": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "estado": "entrante",
                      "recibida_en": "2026-10-24T15:08:12Z",
                      "video": false
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/LlamadasOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope calls:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Las llamadas entrantes",
        "tags": [
          "Llamadas"
        ]
      }
    },
    "/v1/instances/{id}/calls/{call_id}/accept": {
      "post": {
        "description": "Siempre 501 `llamadas_no_soportadas`: el SDK no implementa voz ni vídeo y el motor no simula éxito.\n\n**Scope:** `calls:manage`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `501`: no está implementado.",
        "operationId": "aceptar-llamada",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "call_id",
            "required": true,
            "schema": {
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "501": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Implemented"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Atender una llamada (no soportado)",
        "tags": [
          "Llamadas"
        ]
      }
    },
    "/v1/instances/{id}/calls/{call_id}/offer": {
      "post": {
        "description": "Siempre 501 `llamadas_no_soportadas`: el SDK no implementa voz ni vídeo y el motor no simula éxito.\n\n**Scope:** `calls:manage`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `501`: no está implementado.",
        "operationId": "llamar",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "call_id",
            "required": true,
            "schema": {
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "501": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Implemented"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Hacer una llamada (no soportado)",
        "tags": [
          "Llamadas"
        ]
      }
    },
    "/v1/instances/{id}/calls/{call_id}/reject": {
      "post": {
        "description": "Scope `calls:manage`. Un comando durable (`call.reject`, idempotente por llamada): el resultado en `GET /v1/commands/{id}` y `call.rejected`. El rechazo va al dispositivo y al creador con los que llegó la oferta. `completado` quiere decir que salió: WhatsApp no lo confirma, y el corte en el teléfono de quien llama llega como `call.terminate`. El rechazo automático se configura por instancia (`config.rechazar_llamadas` y `config.mensaje_rechazo`).\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `call.rejected`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "rechazar-llamada",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "call_id",
            "required": true,
            "schema": {
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "call.reject",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope calls:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Rechazar una llamada entrante",
        "tags": [
          "Llamadas"
        ]
      }
    },
    "/v1/instances/{id}/chat-presence": {
      "post": {
        "description": "Scope `presence:write`. En el momento, sin cola (409 `no_conectada` si no está conectada).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "presencia-chat",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destino": {
                  "jid": "CONTACTO@s.whatsapp.net"
                },
                "estado": "escribiendo"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoPresenciaChat"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope presence:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Escribiendo, grabando o pausado en un chat",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/chats": {
      "get": {
        "description": "Scope `chats:read`. Los chats que conoce el motor (por un mensaje o por el appstate), del más activo al menos, con su estado en WhatsApp: fijado, archivado, silenciado (y hasta cuándo), la marca «no leído», si se borró y si tiene candado (solo llega del teléfono: `appstate.changed` con `poner_candado` o `quitar_candado`), más sus etiquetas. La nota de un chat de WhatsApp Business llega como su propio evento, `chat.note` (creada, editada o eliminada; solo del teléfono). Pagina con `next_cursor` (estable aunque lleguen chats nuevos arriba). Filtros: `estado` (coma: fijado, archivado, silenciado, no_leido, borrado; se combinan con «o»), `label_id` y `buscar` (un teléfono o un JID exacto). **«Archivado» en WhatsApp no es «conversación resuelta» del CRM**: es el estado de la app de WhatsApp (lo que ve el teléfono); el CRM lleva sus propios estados y no se sincronizan solos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-chats",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "estado",
            "schema": {
              "examples": [
                "fijado,no_leido"
              ],
              "maxLength": 100,
              "type": "string"
            }
          },
          {
            "description": "Una o más etiquetas (coma): los chats con alguna.",
            "explode": false,
            "in": "query",
            "name": "label_id",
            "schema": {
              "description": "Una o más etiquetas (coma): los chats con alguna.",
              "maxLength": 500,
              "type": "string"
            }
          },
          {
            "description": "Un teléfono internacional o un JID (exacto).",
            "explode": false,
            "in": "query",
            "name": "buscar",
            "schema": {
              "description": "Un teléfono internacional o un JID (exacto).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "chats": [
                    {
                      "actividad_en": "2026-10-24T15:08:12Z",
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "archivado": false,
                      "borrado": false,
                      "candado": false,
                      "chat": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "etiquetas": [
                        {
                          "color": 1,
                          "label_id": "3",
                          "nombre": "Ventas Centro"
                        }
                      ],
                      "fijado": false,
                      "no_leido": false,
                      "silenciado": false
                    }
                  ],
                  "has_more": false
                },
                "schema": {
                  "$ref": "#/components/schemas/ChatsOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope chats:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El estado de los chats en WhatsApp (proyección del appstate)",
        "tags": [
          "Chats"
        ]
      }
    },
    "/v1/instances/{id}/chats/actions": {
      "post": {
        "description": "Scope `chats:manage`. Un comando durable del appstate (`chat.pin`, `chat.archive`, `chat.mute`, `chat.mark_read`, `chat.star` o `chat.delete`): el resultado en `GET /v1/commands/{id}` y `appstate.changed` (con `command_id`). Archivar, marcar y borrar llevan el **rango real** del chat (su último mensaje: el que conoce el motor o `ultimo_mensaje`); sin ninguno, el comando falla con `sin_ultimo_mensaje` (nunca se manda un rango vacío). Un error transitorio (sin sesión, una clave del appstate que falta) se reintenta con su backoff. **`delete` es irreversible** (borra el chat en el teléfono y los dispositivos): exige `confirmar_irreversible: true` y NO borra el ledger ni las entregas del motor. **«Archivado» en WhatsApp no es «conversación resuelta» del CRM**: es el estado de la app de WhatsApp (lo que ve el teléfono); el CRM lleva sus propios estados y no se sincronizan solos.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `appstate.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "accion-chat",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "archivar": {
                  "summary": "Archivar",
                  "value": {
                    "accion": "archive",
                    "destino": {
                      "jid": "CONTACTO@s.whatsapp.net"
                    }
                  }
                },
                "borrar": {
                  "summary": "Borrar",
                  "value": {
                    "accion": "delete",
                    "confirmar_irreversible": true,
                    "destino": {
                      "jid": "CONTACTO@s.whatsapp.net"
                    },
                    "ultimo_mensaje": {
                      "from_me": false,
                      "momento": "2026-10-24T15:08:12Z",
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    }
                  }
                },
                "silenciar": {
                  "summary": "Silenciar",
                  "value": {
                    "accion": "mute",
                    "destino": {
                      "jid": "CONTACTO@s.whatsapp.net"
                    },
                    "duracion_seg": 28800
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoAccionChat"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "chat.mute",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope chats:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Fijar, archivar, silenciar, marcar, destacar o borrar un chat en WhatsApp",
        "tags": [
          "Chats"
        ]
      }
    },
    "/v1/instances/{id}/chats/{peer_ref}": {
      "get": {
        "description": "Scope `chats:read`. **«Archivado» en WhatsApp no es «conversación resuelta» del CRM**: es el estado de la app de WhatsApp (lo que ve el teléfono); el CRM lleva sus propios estados y no se sincronizan solos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-chat",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del chat.",
            "in": "path",
            "name": "peer_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del chat.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actividad_en": "2026-10-24T15:08:12Z",
                  "actualizado_en": "2026-10-24T15:08:12Z",
                  "archivado": false,
                  "borrado": false,
                  "candado": false,
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "etiquetas": [
                    {
                      "color": 1,
                      "label_id": "3",
                      "nombre": "Ventas Centro"
                    }
                  ],
                  "fijado": false,
                  "no_leido": false,
                  "silenciado": false
                },
                "schema": {
                  "$ref": "#/components/schemas/EstadoChat"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope chats:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El estado de un chat en WhatsApp",
        "tags": [
          "Chats"
        ]
      }
    },
    "/v1/instances/{id}/commands": {
      "post": {
        "description": "Responde 202 en cuanto el comando quedó guardado (`status: aceptado`); se ejecuta enseguida y su resultado se consulta con `GET /v1/commands/{id}` (`completado` o `fallido` con `error_code`) y en el estado de la instancia. Scope según el tipo: `instances:manage` para reconnect, disconnect, pause y resume; `instances:logout` para logout y archive. Con `Idempotency-Key`, repetir el pedido devuelve el mismo comando; la misma clave con otro contenido es 409. Antes de ejecutarse se revalida la key: si la revocaron, venció o perdió el scope, el comando termina `fallido`.\n\n**Asíncrona:** responde `202` con el comando guardado; sigue su estado en `GET /v1/commands/{id}` (`completado` o `fallido` con `error_code`). El cambio de la instancia llega como `state.changed`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: la `Idempotency-Key` ya se usó con otro contenido, o la instancia no admite ese comando en su estado.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "comando-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Opcional. Hace el comando idempotente.",
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "description": "Opcional. Hace el comando idempotente.",
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "correlation_id": "crm-op-1234",
                "payload": {
                  "motivo": "Reconexión pedida desde el CRM"
                },
                "type": "instance.reconnect"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoComando"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "instance.reconnect",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Mandar un comando de control a una instancia",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/communities": {
      "post": {
        "description": "Scope `groups:write`. `community.create` (`IsParent`): WhatsApp crea solo su grupo de anuncios, que el motor lee y deja vinculado. El `result` trae el JID de la comunidad. Como un grupo, si pudo salir y no hubo respuesta queda `ambiguo`. Un grupo nuevo dentro de ella es `POST …/groups` con `comunidad`. El pedido a WhatsApp lo arma la forma de Ajustes (`grupos.forma_comunidad`, que queda fija al aceptar el comando; de fábrica, la mínima). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "crear-comunidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "aprobacion": true,
                "descripcion": "Avisos y grupos de la tienda",
                "nombre": "Clientes Centro"
              },
              "schema": {
                "$ref": "#/components/schemas/CrearComunidad"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "community.create",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear una comunidad (P078)",
        "tags": [
          "Comunidades"
        ]
      }
    },
    "/v1/instances/{id}/communities/{comunidad_ref}": {
      "get": {
        "description": "Scope `groups:read`. La comunidad y sus grupos vinculados (una relación por grupo, con su versión). Con `actualizar=true` el motor pide antes la lista a WhatsApp y la concilia: los nuevos se vinculan y los que ya no están se desvinculan (`community.changed`). 422 `no_es_comunidad` si ese grupo no es una comunidad.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-comunidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de la comunidad en esta instancia.",
            "in": "path",
            "name": "comunidad_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref de la comunidad en esta instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "comunidad": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "anuncio": false,
                    "aprobacion": false,
                    "bloqueado": false,
                    "descripcion": "Descripción de ejemplo",
                    "efimero_seg": 1,
                    "es_comunidad": false,
                    "grupo": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "miembro": false,
                    "nombre": "Ventas Centro",
                    "participantes": 1,
                    "rol_propio": "miembro",
                    "suspendido": false,
                    "version": 1
                  },
                  "subgrupos": [
                    {
                      "anuncios": false,
                      "cambio_en": "2026-10-24T15:08:12Z",
                      "conocido": false,
                      "desde": "whatsapp",
                      "grupo": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "nombre": "Ventas Centro",
                      "version": 1
                    }
                  ],
                  "version": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/ComunidadVista"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Una comunidad y sus grupos (P078)",
        "tags": [
          "Comunidades"
        ]
      }
    },
    "/v1/instances/{id}/communities/{comunidad_ref}/links": {
      "post": {
        "description": "Scope `groups:write`. `community.link`: el número tiene que administrar la comunidad (si no, `sin_permiso`). Después el motor lee los grupos de la comunidad y concilia la lista; un vínculo que ya estaba (un reintento) no es un error y no se duplica. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined` (y `community.changed` al conciliar la lista), con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "vincular-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de la comunidad en esta instancia.",
            "in": "path",
            "name": "comunidad_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref de la comunidad en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "grupo": {
                  "jid": "GRUPO@g.us"
                },
                "vincular": true
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoVinculo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "community.link",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Vincular o desvincular un grupo de la comunidad (P078)",
        "tags": [
          "Comunidades"
        ]
      }
    },
    "/v1/instances/{id}/communities/{comunidad_ref}/participants": {
      "get": {
        "description": "Scope `groups:read`. Se consultan a WhatsApp en el momento (GetLinkedGroupsParticipants): no se guardan.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "participantes-comunidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref de la comunidad en esta instancia.",
            "in": "path",
            "name": "comunidad_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref de la comunidad en esta instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "participantes": [
                    {
                      "jid": "CONTACTO@s.whatsapp.net"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ParticipantesComunidadOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los participantes de los grupos de la comunidad",
        "tags": [
          "Comunidades"
        ]
      }
    },
    "/v1/instances/{id}/contacts": {
      "get": {
        "description": "Scope `contacts:read`. Los contactos que conoce el número: los de su libreta sincronizada (cómo los guardó el teléfono), los que mandaron su nombre (push name), su nombre de negocio, el ID de su foto y su recado, en el orden en que el motor los conoció (`next_cursor` estable). Filtros: `libreta` (solo los guardados en el teléfono) y `buscar` (un teléfono o un JID exacto). Los cambios llegan como `contact.updated` (libreta), `contact.push_name`, `contact.business_name`, `contact.picture` y `contact.about`. **Son los contactos de transporte del número, no los del CRM**: cómo los guardó el teléfono, el nombre que mandan, su foto y su recado. Nunca se fusionan por nombre ni se convierte un LID en teléfono.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-contactos",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Solo los guardados en la libreta del teléfono.",
            "explode": false,
            "in": "query",
            "name": "libreta",
            "schema": {
              "description": "Solo los guardados en la libreta del teléfono.",
              "type": "boolean"
            }
          },
          {
            "description": "Un teléfono internacional o un JID (exacto).",
            "explode": false,
            "in": "query",
            "name": "buscar",
            "schema": {
              "description": "Un teléfono internacional o un JID (exacto).",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "contactos": [
                    {
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "contacto": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "creado_en": "2026-10-24T15:08:12Z",
                      "en_libreta": false
                    }
                  ],
                  "has_more": false
                },
                "schema": {
                  "$ref": "#/components/schemas/ContactosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los contactos de transporte del número",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/check": {
      "post": {
        "description": "Scope `contacts:lookup`. Para cada número: si tiene cuenta, su JID canónico (puede ser un LID), el JID de su teléfono y si es una cuenta de WhatsApp Business verificada. Si la instancia ya conocía al contacto, el par PN↔LID que dio el servidor queda comprobado en su peer (`peer_ref`). **No es un oráculo público**: cada número (o perfil) consume una consulta de la cuota diaria de la app (`limites.consultas_identidad_dia`, o la de la app) con un máximo por consulta (`limites.numeros_por_consulta`). Un número inválido (422 con sus posiciones) o la cuota agotada (429 `cuota_agotada` con `Retry-After`) rechazan la consulta entera ANTES de llegar al servidor y sin consumir nada. Sin conexión, 409 `no_conectada`. Una consulta no crea contactos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.",
        "operationId": "consultar-numeros",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "telefonos": [
                  "+NUMERO_DEL_CONTACTO"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoConsultaNumeros"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cuota": {
                    "cuota": 1,
                    "maximo_por_consulta": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "resultados": [
                    {
                      "registrado": false,
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ConsultaNumerosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:lookup.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "¿Están en WhatsApp? (IsOnWhatsApp)",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/info": {
      "post": {
        "description": "Scope `contacts:lookup`. Su recado (si lo comparte con este número), el ID de su foto, su nombre verificado de negocio, su LID y cuántos dispositivos tiene. Si la instancia ya conocía al contacto, su recado y su foto quedan en el contacto (con `contact.about` y `contact.picture` si cambiaron, `origen: consulta`). **No es un oráculo público**: cada número (o perfil) consume una consulta de la cuota diaria de la app (`limites.consultas_identidad_dia`, o la de la app) con un máximo por consulta (`limites.numeros_por_consulta`). Un número inválido (422 con sus posiciones) o la cuota agotada (429 `cuota_agotada` con `Retry-After`) rechazan la consulta entera ANTES de llegar al servidor y sin consumir nada. Sin conexión, 409 `no_conectada`. Una consulta no crea contactos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.",
        "operationId": "consultar-perfiles",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destinos": [
                  {
                    "telefono": "+NUMERO_DEL_CONTACTO"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoInfoContactos"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cuota": {
                    "cuota": 1,
                    "maximo_por_consulta": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "perfiles": [
                    {
                      "dispositivos": 1,
                      "jid": "CONTACTO@s.whatsapp.net"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/InfoContactosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:lookup.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El perfil público de unos usuarios (GetUserInfo)",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/picture": {
      "post": {
        "description": "Scope `contacts:lookup`. Su ID y la URL temporal del CDN de WhatsApp; si su privacidad no se la muestra a este número, `estado: oculta` (no es un error); sin foto, `sin_foto`. Usa una consulta de la cuota diaria de la app. Si la instancia ya lo conocía, su foto queda en el contacto. **No es un oráculo público**: cada número (o perfil) consume una consulta de la cuota diaria de la app (`limites.consultas_identidad_dia`, o la de la app) con un máximo por consulta (`limites.numeros_por_consulta`). Un número inválido (422 con sus posiciones) o la cuota agotada (429 `cuota_agotada` con `Retry-After`) rechazan la consulta entera ANTES de llegar al servidor y sin consumir nada. Sin conexión, 409 `no_conectada`. Una consulta no crea contactos.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.",
        "operationId": "foto-contacto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destino": {
                  "jid": "CONTACTO@s.whatsapp.net"
                },
                "vista_previa": true
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoFotoContacto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cuota": {
                    "cuota": 1,
                    "maximo_por_consulta": 1,
                    "renueva": "2026-10-24T15:08:12Z",
                    "usadas": 1
                  },
                  "foto": {
                    "estado": "disponible"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/FotoContactoOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:lookup.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La foto de perfil de otro",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/quota": {
      "get": {
        "description": "Scope `contacts:lookup`. La cuota es de la app (todas sus instancias) y vuelve a cero a las 00:00 UTC. La gastan «¿está en WhatsApp?», la info de perfiles, la foto de un contacto y el perfil comercial; `desglose` dice cuánto se usó hoy en cada una, según la auditoría (una consulta en curso todavía no figura). El catálogo y las colecciones no la gastan: usan la cuota comercial, que viene con su propio `desglose` en cada respuesta comercial.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cuota-consultas",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cuota": 1,
                  "maximo_por_consulta": 1,
                  "renueva": "2026-10-24T15:08:12Z",
                  "usadas": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/Cuota"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:lookup.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La cuota de consultas de la app hoy",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/sync": {
      "post": {
        "description": "Scope `contacts:read`. Pasa a la proyección lo que el SDK guardó de la libreta del teléfono y los nombres que aprendió (también los del historial, que no dejan evento). Pasa solo al conectar; no consulta al servidor ni consume la cuota, y no deja eventos (es el estado, no un cambio). 409 `no_conectada` si la instancia no tiene sesión abierta.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "sincronizar-contactos",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cambiados": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/SincronizacionContactosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Traer la libreta del store a los contactos",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/contacts/{peer_ref}": {
      "get": {
        "description": "Scope `contacts:read`. **Son los contactos de transporte del número, no los del CRM**: cómo los guardó el teléfono, el nombre que mandan, su foto y su recado. Nunca se fusionan por nombre ni se convierte un LID en teléfono.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-contacto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del contacto.",
            "in": "path",
            "name": "peer_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del contacto.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizado_en": "2026-10-24T15:08:12Z",
                  "contacto": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "creado_en": "2026-10-24T15:08:12Z",
                  "en_libreta": false
                },
                "schema": {
                  "$ref": "#/components/schemas/ContactoVista"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Un contacto de transporte",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/diagnostics": {
      "get": {
        "description": "Scope `instances:read`. Estado conciliado y sesión real, último evento (tipo y tiempos, no contenido), lo pendiente, el último error tipificado, reconexiones, keepalive, el pool de la base y las alertas abiertas. Sin teléfono, JID, texto, QR, códigos ni claves.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "diagnostico-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "alertas": [
                    {
                      "abierta_en": "2026-10-24T15:08:12Z",
                      "cerrada_en": "2026-10-24T15:08:12Z",
                      "cierre": "texto",
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "instancia_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                      "motivo": "pedido del cliente",
                      "ocurrencias": 1,
                      "severidad": "critica",
                      "tipo": "instancia_caida",
                      "ultima_vez": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "caida_desde": "2026-10-24T15:08:12Z",
                  "checked_at": "2026-10-24T15:08:12Z",
                  "estado": "texto",
                  "estado_deseado": "texto",
                  "instancia_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "keepalive": {
                    "errores_seguidos": 1,
                    "ultima_vuelta": "2026-10-24T15:08:12Z",
                    "ultimo_fallo": "2026-10-24T15:08:12Z"
                  },
                  "motivo": "pedido del cliente",
                  "multimedia": {
                    "almacenamiento": "disponible",
                    "fallidos_24h": 1,
                    "pendientes": 1,
                    "presion_disco": false
                  },
                  "pendiente": {
                    "comandos": 1,
                    "eventos_sin_entregar": 1,
                    "ultimo_seq": 1187
                  },
                  "pool": {
                    "abiertas": 1,
                    "cerradas_por_vida": 1,
                    "en_uso": 1,
                    "espera_total_ms": 1,
                    "esperas": 1,
                    "max": 1,
                    "ociosas": 1
                  },
                  "proceso": {
                    "dueno": false,
                    "transporte": false
                  },
                  "reconexiones": {
                    "automatica": false,
                    "bloqueada_hasta": "2026-10-24T15:08:12Z",
                    "desconexiones_24h": 1,
                    "proximo_intento_en": "2026-10-24T15:08:12Z",
                    "reintentos": 1,
                    "reintentos_proceso": 1,
                    "total": 1
                  },
                  "sesion": {
                    "abierta": false,
                    "autenticada": false,
                    "conectada": false
                  },
                  "ultimo_error": {
                    "codigo": "texto",
                    "en": "2026-10-24T15:08:12Z"
                  },
                  "ultimo_evento": {
                    "lag_ms": 1,
                    "occurred_at": "2026-10-24T15:08:12Z",
                    "received_at": "2026-10-24T15:08:12Z",
                    "seq": 1187,
                    "tipo": "message.received"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Diagnostico"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Diagnóstico de una instancia (sin datos personales)",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/events": {
      "get": {
        "description": "Scope `events:read`. Los eventos persistidos de una instancia de tu app, en orden de `seq` (la secuencia de commit del motor por instancia, no el orden de WhatsApp), después de `after_seq`. Cada evento es el envelope del plan §5.4: `schema_version`, `event_id`, `instance_id`, `seq`, `type`, `occurred_at`, `received_at`, `generation`, `origin` (`live`, `history` u `operator`), `command_id`, `correlation_id` y `data`. Tipos de la MW3: `message.received`, `message.updated` (edición, revocación, reacción o cambio de `estado`, que nunca retrocede), `message.undecryptable` (sin texto), `receipt`, `history.sync` (metadatos), `message.sent`, `command.*` y los de estado. `message.expired` (FIX-A1 R14): un mensaje temporal pasó su vencimiento (su momento más `expiracion_seg`; WhatsApp no avisa nada) y el motor borró su contenido y sus medios; sale una vez por mensaje, con `chat`, `autor`, `provider_id`, `from_me`, `message_ref`, `momento` y `vence_en`. Desde ese momento, el `message.received` (y la edición) de ese mensaje sale sin `contenido`, con `redactado: true` y `motivo: vencido`; un mensaje que lo cita (temporal o no) conserva su contenido, pero su `contenido.cita` queda solo con `provider_id` y `citado_vencido: true` (el motor tampoco guarda ya el texto ni los medios citados). Para seguir leyendo, usa `next_after_seq`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "eventos-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Devuelve los eventos con seq mayor que este.",
            "explode": false,
            "in": "query",
            "name": "after_seq",
            "schema": {
              "default": 0,
              "description": "Devuelve los eventos con seq mayor que este.",
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Tipos separados por coma (vacío: todos).",
            "explode": false,
            "in": "query",
            "name": "types",
            "schema": {
              "description": "Tipos separados por coma (vacío: todos).",
              "examples": [
                "message.received,receipt"
              ],
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "format": "int64",
              "maximum": 500,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "events": [
                    {
                      "data": {},
                      "event_id": "8a1d2c3e-0000-4000-8000-0000a08b063d",
                      "generation": 1,
                      "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                      "occurred_at": "2026-10-24T15:08:12Z",
                      "origin": "live",
                      "received_at": "2026-10-24T15:08:12Z",
                      "schema_version": 1,
                      "seq": 1187,
                      "type": "message.received"
                    }
                  ],
                  "has_more": false,
                  "next_after_seq": 1187
                },
                "schema": {
                  "$ref": "#/components/schemas/ListaEventosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Leer el ledger de eventos de una instancia",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/instances/{id}/events/stream": {
      "get": {
        "description": "Scope `events:read`. Los eventos del ledger en vivo, con el mismo envelope que la API de eventos y los webhooks (y la misma redacción por retención). **Sin cursor**, empieza en lo que llegue desde ahora (la trama `listo` trae el cursor de partida). **Para reanudar**, manda el último cursor recibido en `Last-Event-ID` (SSE lo hace solo) o en `?desde=`: reanudar no salta ni repite un evento. Un cursor de otra app es 403; uno alterado, 422; uno con eventos sin leer más viejos que la retención (Ajustes → Streams) es **410** con `primer_cursor` (usarlo es aceptar el salto: nunca se salta en silencio). El orden es el de `seq` dentro de cada instancia; entre instancias, por llegada. El motor corta el stream con una trama `cierre` (su `motivo`, si es `reanudable` y el `cursor`): `credencial_revocada` (key revocada o vencida, o la app suspendida), `sin_scope`, `apagado` (el motor se reinicia: reanuda con el cursor), `cortado_por_operador` o `error_interno`. **Un `cliente_lento`** (el cliente no lee y su buffer quedó lleno) **se corta sin trama**: SSE cierra la conexión y WebSocket la corta sin close frame. Reconecta con el último cursor que recibiste; el motivo queda en `GET /v1/events/streams`. Hay un tope de streams abiertos por app (429). En el stream de una instancia, `desde` también puede ser un `seq`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "stream-eventos-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
            "explode": false,
            "in": "query",
            "name": "desde",
            "schema": {
              "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
            "in": "header",
            "name": "Last-Event-ID",
            "schema": {
              "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "Tipos separados por coma (vacío: todos).",
            "explode": false,
            "in": "query",
            "name": "types",
            "schema": {
              "description": "Tipos separados por coma (vacío: todos).",
              "examples": [
                "message.received,receipt"
              ],
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
            "explode": false,
            "in": "query",
            "name": "contrato",
            "schema": {
              "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
              "examples": [
                "1"
              ],
              "maxLength": 16,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "`text/event-stream`: `event: listo` (con el cursor de partida), `event: evento` (con `id:` = su cursor y el envelope en `data:`), comentarios de keepalive y `event: cierre` con el motivo (un `cliente_lento` se corta sin ella)."
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Stream de eventos de una instancia (SSE)",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/instances/{id}/events/ws": {
      "get": {
        "description": "Scope `events:read`. Los eventos del ledger en vivo, con el mismo envelope que la API de eventos y los webhooks (y la misma redacción por retención). **Sin cursor**, empieza en lo que llegue desde ahora (la trama `listo` trae el cursor de partida). **Para reanudar**, manda el último cursor recibido en `Last-Event-ID` (SSE lo hace solo) o en `?desde=`: reanudar no salta ni repite un evento. Un cursor de otra app es 403; uno alterado, 422; uno con eventos sin leer más viejos que la retención (Ajustes → Streams) es **410** con `primer_cursor` (usarlo es aceptar el salto: nunca se salta en silencio). El orden es el de `seq` dentro de cada instancia; entre instancias, por llegada. El motor corta el stream con una trama `cierre` (su `motivo`, si es `reanudable` y el `cursor`): `credencial_revocada` (key revocada o vencida, o la app suspendida), `sin_scope`, `apagado` (el motor se reinicia: reanuda con el cursor), `cortado_por_operador` o `error_interno`. **Un `cliente_lento`** (el cliente no lee y su buffer quedó lleno) **se corta sin trama**: SSE cierra la conexión y WebSocket la corta sin close frame. Reconecta con el último cursor que recibiste; el motivo queda en `GET /v1/events/streams`. Hay un tope de streams abiertos por app (429). En el stream de una instancia, `desde` también puede ser un `seq`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "stream-eventos-instancia-ws",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
            "explode": false,
            "in": "query",
            "name": "desde",
            "schema": {
              "description": "El cursor desde el que reanudar (el último recibido). Gana sobre Last-Event-ID.",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
            "in": "header",
            "name": "Last-Event-ID",
            "schema": {
              "description": "El cursor del último evento recibido (SSE lo manda solo al reconectar).",
              "maxLength": 65536,
              "type": "string"
            }
          },
          {
            "description": "Tipos separados por coma (vacío: todos).",
            "explode": false,
            "in": "query",
            "name": "types",
            "schema": {
              "description": "Tipos separados por coma (vacío: todos).",
              "examples": [
                "message.received,receipt"
              ],
              "maxLength": 1000,
              "type": "string"
            }
          },
          {
            "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
            "explode": false,
            "in": "query",
            "name": "contrato",
            "schema": {
              "description": "La versión del contrato de eventos que espera el cliente (vacío: la vigente).",
              "examples": [
                "1"
              ],
              "maxLength": 16,
              "type": "string"
            }
          }
        ],
        "responses": {
          "101": {
            "description": "Cambia a WebSocket. Mensajes JSON de texto: `{\"tipo\":\"listo\",\"id\":<cursor>,\"listo\":{…}}`, `{\"tipo\":\"evento\",\"id\":<cursor>,\"evento\":<envelope>}`, `{\"tipo\":\"keepalive\"}` y `{\"tipo\":\"cierre\",\"cierre\":{\"motivo\",\"reanudable\",\"cursor\"}}`; el close frame lleva el motivo. Un `cliente_lento` se corta sin trama `cierre` ni close frame."
          },
          "200": {
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope events:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Stream de eventos de una instancia (WebSocket)",
        "tags": [
          "Eventos"
        ]
      }
    },
    "/v1/instances/{id}/groups": {
      "get": {
        "description": "Scope `groups:read`. Lo que el motor sabe de cada grupo (la proyección de esta instancia: el mismo grupo en otro número es otra fila), con `next_cursor` y `has_more`. Con `actualizar=true` el motor pide antes la lista a WhatsApp (los que ya no están quedan `miembro: false`).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-grupos",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Primero pide la lista a WhatsApp (409 no_conectada sin conexión).",
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "description": "Primero pide la lista a WhatsApp (409 no_conectada sin conexión).",
              "type": "boolean"
            }
          },
          {
            "description": "Solo las comunidades (MW8c).",
            "explode": false,
            "in": "query",
            "name": "comunidades",
            "schema": {
              "description": "Solo las comunidades (MW8c).",
              "type": "boolean"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "grupos": [
                    {
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "anuncio": false,
                      "aprobacion": false,
                      "bloqueado": false,
                      "descripcion": "Descripción de ejemplo",
                      "efimero_seg": 1,
                      "es_comunidad": false,
                      "grupo": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "miembro": false,
                      "nombre": "Ventas Centro",
                      "participantes": 1,
                      "rol_propio": "miembro",
                      "suspendido": false,
                      "version": 1
                    }
                  ],
                  "has_more": false
                },
                "schema": {
                  "$ref": "#/components/schemas/GruposOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los grupos del número (P068)",
        "tags": [
          "Grupos"
        ]
      },
      "post": {
        "description": "Scope `groups:write`. `group.create`: el `result` trae el JID del grupo y el resultado de cada participante tal como vino (`codigo` 0: entró; 403: su privacidad no deja agregarlo y viene una `invitacion`; 409: ya estaba…). Si el proceso cae a mitad o el servidor no contesta, el comando queda `ambiguo` (`resultado_incierto`): nunca se crea dos veces a ciegas. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "crear-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "efimero_seg": 604800,
                "nombre": "Pedidos Centro",
                "participantes": [
                  {
                    "telefono": "+NUMERO_DEL_CONTACTO"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CrearGrupo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.create",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear un grupo (P063)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/invite/info": {
      "post": {
        "description": "Scope `groups:read`. Lo que WhatsApp dice del grupo de un enlace (nombre, participantes, si exige aprobación). Una invitación que no es válida es 404 `invitacion_invalida`; revocada o vencida, 410 `invitacion_revocada`. Sin conexión, 409.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "info-invitacion",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "enlace": "https://chat.whatsapp.com/CODIGO_DE_INVITACION"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEnlace"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "aprobacion": false,
                  "es_comunidad": false,
                  "jid": "CONTACTO@s.whatsapp.net",
                  "nombre": "Ventas Centro",
                  "participantes": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/InvitacionInfo"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Consultar una invitación sin entrar (P070)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/join": {
      "post": {
        "description": "Scope `groups:write`. `group.join`: el `result` trae el JID del grupo y `pendiente_aprobacion` si el grupo exige que un administrador apruebe la entrada. Inválida: `invitacion_invalida`; revocada o vencida: `invitacion_revocada`; si el número ya estaba en el grupo, `ya_es_miembro`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "unirse-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "enlace": "https://chat.whatsapp.com/CODIGO_DE_INVITACION"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEnlace"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.join",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Entrar a un grupo con una invitación (P071)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}": {
      "get": {
        "description": "Scope `groups:read`. La información del grupo, el rol del número (`rol_propio`) y los participantes con su rol. Con `actualizar=true` el motor lo consulta antes a WhatsApp.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "grupo": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "anuncio": false,
                    "aprobacion": false,
                    "bloqueado": false,
                    "descripcion": "Descripción de ejemplo",
                    "efimero_seg": 1,
                    "es_comunidad": false,
                    "grupo": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "miembro": false,
                    "nombre": "Ventas Centro",
                    "participantes": 1,
                    "rol_propio": "miembro",
                    "suspendido": false,
                    "version": 1
                  },
                  "participantes": [
                    {
                      "cambio_en": "2026-10-24T15:08:12Z",
                      "desde": "whatsapp",
                      "participante": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "rol": "miembro"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/GrupoOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Un grupo y sus participantes (P067)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/description": {
      "put": {
        "description": "Scope `groups:write`. `group.description` (vacía la borra). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "descripcion-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "texto": "Pedidos y entregas de la tienda Centro."
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoDescripcionGrupo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.description",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar la descripción del grupo (P066)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/invite-link": {
      "post": {
        "description": "Scope `groups:write`. `group.invite_link`: el `result` trae el enlace (solo un administrador lo puede pedir); con `revocar`, el vigente deja de servir. El último enlace queda en el grupo (`invitacion`). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "enlace-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "revocar": false
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoRevocar"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.invite_link",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Obtener o revocar el enlace de invitación (P069)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/invite/send": {
      "post": {
        "description": "Scopes `groups:read` y `messages:send`. Manda el último enlace del grupo (409 `sin_enlace` si el motor todavía no lo pidió) a cada destino como un mensaje de texto por el mismo outbox (con su ritmo y su cuota): no inscribe a nadie. Devuelve un comando por destino (Idempotency-Key + «:n»).\n\n**Asíncrona:** responde `202` con un comando por destino (cada uno, un mensaje de texto por el outbox); sigue cada uno en `GET /v1/commands/{id}`. Llegan `command.accepted`, `message.sent`, `command.failed` o `command.ambiguous` por cada envío.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.",
        "operationId": "enviar-invitacion",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 190,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destinos": [
                  {
                    "telefono": "+NUMERO_DEL_CONTACTO"
                  }
                ],
                "texto": "Te invitamos al grupo de pedidos:"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEnviarInvitacion"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "comandos": [
                    {
                      "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                      "created_at": "2026-10-24T15:08:12Z",
                      "generation": 1,
                      "idempotency_key": "crm-envio-0001",
                      "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                      "status": "en_cola",
                      "type": "message.text",
                      "updated_at": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "enlace": "https://chat.whatsapp.com/CODIGO_DE_INVITACION"
                },
                "schema": {
                  "$ref": "#/components/schemas/InvitacionesOutputBody"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Mandar la invitación del grupo (P072)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/leave": {
      "post": {
        "description": "Scope `groups:write`. `group.leave`: el grupo queda `miembro: false`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "salir-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.leave",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Salir del grupo (P077)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/name": {
      "put": {
        "description": "Scope `groups:write`. `group.name` (hasta 25 caracteres). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "nombre-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "nombre": "Pedidos Centro"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoNombreGrupo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.name",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar el nombre del grupo (P064)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/participants": {
      "post": {
        "description": "Scope `groups:write`. `group.participants`: el `result` trae el resultado de cada participante tal como vino (`codigo` 0: hecho; si no, el código del servidor), con `hechos` y `fallidos`; `group.participants` dice lo que cambió. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "participantes-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "accion": "add",
                "participantes": [
                  {
                    "telefono": "+NUMERO_DEL_CONTACTO"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoParticipantes"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.participants",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Agregar, quitar, promover o degradar participantes (P073)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/picture": {
      "delete": {
        "description": "Scope `groups:write`. `group.picture` con `quitar`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "quitar-foto-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.picture",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Quitar la foto del grupo (P065)",
        "tags": [
          "Grupos"
        ]
      },
      "put": {
        "description": "Scope `groups:write`. `group.picture` con un JPEG subido a esta instancia (hasta 2 MB, de 192 a 2048 píxeles por lado; el motor la recorta al centro y la deja en 640 × 640, la medida que acepta WhatsApp). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "foto-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoFoto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.picture",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar la foto del grupo (P065)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/requests": {
      "get": {
        "description": "Scope `groups:read`. Se consultan a WhatsApp en el momento (solo un administrador; 403 `sin_permiso` si no).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "solicitudes-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "solicitudes": [
                    {
                      "jid": "CONTACTO@s.whatsapp.net",
                      "momento": "2026-10-24T15:08:12Z"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/SolicitudesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los pedidos para entrar (P075)",
        "tags": [
          "Grupos"
        ]
      },
      "post": {
        "description": "Scope `groups:write`. `group.requests`, con el resultado de cada uno en `result`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "resolver-solicitudes",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "accion": "approve",
                "participantes": [
                  {
                    "jid": "CONTACTO@s.whatsapp.net"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoSolicitudes"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.requests",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Aprobar o rechazar pedidos para entrar (P075)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/groups/{grupo_ref}/settings": {
      "put": {
        "description": "Scope `groups:write`. `group.setting`, un ajuste por comando: `announce` (solo los administradores escriben), `locked` (solo ellos editan la información), `approval` (entrar exige aprobación) o `member_add` con `modo` (quién agrega). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `group.changed`, `group.participants` o `group.joined` con su `command_id`. Los permisos los decide WhatsApp: si el número no es administrador, el comando falla con `sin_permiso` (o `no_es_miembro`, `grupo_no_encontrado`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `group.changed`, `group.participants` o `group.joined`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ajuste-grupo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del grupo en esta instancia.",
            "in": "path",
            "name": "grupo_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del grupo en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "anuncio": {
                  "summary": "Anuncio",
                  "value": {
                    "ajuste": "announce",
                    "valor": true
                  }
                },
                "quien_agrega": {
                  "summary": "Quien agrega",
                  "value": {
                    "ajuste": "member_add",
                    "modo": "admin_add"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoAjusteGrupo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "group.setting",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope groups:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar un ajuste del grupo (P074, P075)",
        "tags": [
          "Grupos"
        ]
      }
    },
    "/v1/instances/{id}/history": {
      "get": {
        "description": "Scope `history:read`. La política vigente (la de la instancia o la de Ajustes: importar viene apagado; los metadatos y el protocolo se procesan siempre), los trabajos más nuevos primero con su progreso y su resultado parcial, y cuántos lotes llegaron. WhatsApp no garantiza la historia completa: un trabajo dice lo que llegó (importados, duplicados, omitidos por el corte o la cuota) y nunca «toda la historia». El teléfono tiene que estar en línea para contestar un pedido.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-historial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El next_cursor de la página anterior (recorre los trabajos empatados sin saltarlos).",
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "El next_cursor de la página anterior (recorre los trabajos empatados sin saltarlos).",
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Obsoleto: usa cursor. Los trabajos creados antes de este momento (salta los empatados con el último).",
            "explode": false,
            "in": "query",
            "name": "antes",
            "schema": {
              "description": "Obsoleto: usa cursor. Los trabajos creados antes de este momento (salta los empatados con el último).",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 20,
              "format": "int64",
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "aviso": "texto",
                  "has_more": false,
                  "lotes": {
                    "importados": 1,
                    "omitidos": 1,
                    "pendientes": 1,
                    "recibidos": 1,
                    "sin_contenido": 1
                  },
                  "politica": {
                    "dias": 1,
                    "importar": false,
                    "max_mensajes": 1,
                    "medios": false,
                    "propia": false
                  },
                  "trabajos": [
                    {
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "aviso": "texto",
                      "cantidad": 1,
                      "chat_actual": 1,
                      "chats": [
                        "texto"
                      ],
                      "creado_en": "2026-10-24T15:08:12Z",
                      "duplicados": 1,
                      "estado": "en_curso",
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "importados": 1,
                      "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                      "lotes_importados": 1,
                      "lotes_recibidos": 1,
                      "max_mensajes": 1,
                      "mensajes_vistos": 1,
                      "no_soportados": 1,
                      "omitidos_cuota": 1,
                      "omitidos_fecha": 1,
                      "pedidos": 1,
                      "sin_respuesta": 1,
                      "tipo": "inicial"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/EstadoHistorial"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope history:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La política del historial y sus trabajos",
        "tags": [
          "Historial"
        ]
      }
    },
    "/v1/instances/{id}/history/imports": {
      "post": {
        "description": "Scope `history:manage`. `history.import`: pedidos sucesivos hacia atrás, chat por chat (vacío: los 20 con actividad más reciente), hasta el corte en días, la cuota o lo que tenga el teléfono, con la contrapresión de las entregas (con demasiadas pendientes, el trabajo queda `en_pausa`). La importación tiene que estar encendida. WhatsApp no garantiza la historia completa: un trabajo dice lo que llegó (importados, duplicados, omitidos por el corte o la cuota) y nunca «toda la historia». El teléfono tiene que estar en línea para contestar un pedido.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `sync.progress`, `sync.completed` o `sync.failed`; los mensajes importados llegan como `message.received` con `origin: history`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "importar-historial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "chats": [
                  {
                    "jid": "CONTACTO@s.whatsapp.net"
                  }
                ],
                "dias": 30,
                "max_mensajes": 5000
              },
              "schema": {
                "$ref": "#/components/schemas/ImportarHistorial"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "history.import",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope history:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Importar el historial de varios chats",
        "tags": [
          "Historial"
        ]
      }
    },
    "/v1/instances/{id}/history/jobs/{job_id}": {
      "get": {
        "description": "Scope `history:read`. Su estado, su progreso y su resultado parcial. WhatsApp no garantiza la historia completa: un trabajo dice lo que llegó (importados, duplicados, omitidos por el corte o la cuota) y nunca «toda la historia». El teléfono tiene que estar en línea para contestar un pedido.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-trabajo-historial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "ID del trabajo (el command_id del comando que lo creó).",
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "description": "ID del trabajo (el command_id del comando que lo creó).",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizado_en": "2026-10-24T15:08:12Z",
                  "aviso": "texto",
                  "cantidad": 1,
                  "chat_actual": 1,
                  "chats": [
                    "texto"
                  ],
                  "creado_en": "2026-10-24T15:08:12Z",
                  "duplicados": 1,
                  "estado": "en_curso",
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "importados": 1,
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "lotes_importados": 1,
                  "lotes_recibidos": 1,
                  "max_mensajes": 1,
                  "mensajes_vistos": 1,
                  "no_soportados": 1,
                  "omitidos_cuota": 1,
                  "omitidos_fecha": 1,
                  "pedidos": 1,
                  "sin_respuesta": 1,
                  "tipo": "inicial"
                },
                "schema": {
                  "$ref": "#/components/schemas/TrabajoSync"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope history:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Un trabajo de historial",
        "tags": [
          "Historial"
        ]
      }
    },
    "/v1/instances/{id}/history/jobs/{job_id}/cancel": {
      "post": {
        "description": "Scope `history:manage`. Deja de importar: lo que faltaba se omite y su contenido guardado se borra (`sync.failed` con `motivo: cancelado`). Lo ya importado queda. 409 `trabajo_terminado` si ya terminó.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cancelar-trabajo-historial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "ID del trabajo (el command_id del comando que lo creó).",
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "description": "ID del trabajo (el command_id del comando que lo creó).",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizado_en": "2026-10-24T15:08:12Z",
                  "aviso": "texto",
                  "cantidad": 1,
                  "chat_actual": 1,
                  "chats": [
                    "texto"
                  ],
                  "creado_en": "2026-10-24T15:08:12Z",
                  "duplicados": 1,
                  "estado": "en_curso",
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "importados": 1,
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "lotes_importados": 1,
                  "lotes_recibidos": 1,
                  "max_mensajes": 1,
                  "mensajes_vistos": 1,
                  "no_soportados": 1,
                  "omitidos_cuota": 1,
                  "omitidos_fecha": 1,
                  "pedidos": 1,
                  "sin_respuesta": 1,
                  "tipo": "inicial"
                },
                "schema": {
                  "$ref": "#/components/schemas/TrabajoSync"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope history:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cancelar un trabajo de historial",
        "tags": [
          "Historial"
        ]
      }
    },
    "/v1/instances/{id}/history/requests": {
      "post": {
        "description": "Scope `history:manage`. `history.request`: pide al teléfono los N mensajes anteriores al más viejo que el motor conoce de ese chat (409 `sin_mensajes` si no conoce ninguno; 409 `importacion_apagada` con la importación apagada). Crea un trabajo con el mismo ID que el comando: `GET …/history/jobs/{command_id}`, con `sync.progress`, `sync.completed` o `sync.failed` (sin respuesta del teléfono a tiempo, `sin_respuesta`: sin conexión o sin nada más viejo de ese chat). Si el teléfono dijo en el historial que no le quedan mensajes de ese chat, termina sin pedir (`sin_mas_historial`); como WhatsApp Web, un chat que no vino en el historial inicial del vínculo con mensajes que se pueden pedir (por ejemplo, uno que empezó después de vincular) termina sin pedir (`fuera_del_historial` o `solo_en_el_telefono`). El chat va como lo nombró el teléfono en el historial (si no vino en uno, por su PN); las variantes del pedido están en Ajustes (`historial.pedido_*`). Lo importado llega como `message.received` con `origin: history`, con la misma identidad que en vivo (no se duplica). WhatsApp no garantiza la historia completa: un trabajo dice lo que llegó (importados, duplicados, omitidos por el corte o la cuota) y nunca «toda la historia». El teléfono tiene que estar en línea para contestar un pedido.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `sync.progress`, `sync.completed` o `sync.failed`; los mensajes importados llegan como `message.received` con `origin: history`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "pedir-historial",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "cantidad": 50,
                "destino": {
                  "jid": "CONTACTO@s.whatsapp.net"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoPedidoHistorial"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "history.request",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope history:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Pedir más historial de un chat (P052)",
        "tags": [
          "Historial"
        ]
      }
    },
    "/v1/instances/{id}/identities": {
      "get": {
        "description": "Scope `contacts:read`. Con un `telefono`, un `jid` o un `peer_ref` (uno solo): su peer estable y sus alias **comprobados por esta instancia** (el PN y el LID que el servidor le informó juntos). No consulta al servidor ni a otras instancias: lo que esta instancia no comprobó no aparece (404 `identidad_desconocida`). Un LID nunca se convierte en teléfono y nada se fusiona por nombre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "resolver-identidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "telefono",
            "schema": {
              "maxLength": 32,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "jid",
            "schema": {
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "description": "Un peer_ref de esta instancia.",
            "explode": false,
            "in": "query",
            "name": "peer_ref",
            "schema": {
              "description": "Un peer_ref de esta instancia.",
              "maxLength": 36,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "aliases": [
                    "CONTACTO@lid"
                  ],
                  "clase": "usuario",
                  "contacto": false,
                  "jid": "CONTACTO@s.whatsapp.net",
                  "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                },
                "schema": {
                  "$ref": "#/components/schemas/Identidad"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope contacts:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Resolver una identidad (LID↔PN) en esta instancia",
        "tags": [
          "Contactos"
        ]
      }
    },
    "/v1/instances/{id}/interactive-responses": {
      "get": {
        "description": "Scope `messages:read`. Las respuestas que llegaron (botón, fila de lista, plantilla o native flow), las más nuevas primero, con `next_cursor` estable y `has_more`. Cada una con su `correlacion`: `correlacionada` (un interactivo de esta instancia y de ese chat, con la acción que eligió), `accion_desconocida`, `sin_mensaje`, `otro_chat`, `otro_autor` (el contexto dice que el mensaje citado es de otro autor, no del número de esta instancia, o su autor no es válido), `no_respondible` o `desconocida` (un formato que no se pudo leer: llegó como `interactive.unknown`). Cada una es también un evento durable (`interactive.response`). `otro_chat` y `otro_autor` son revisables: si después esta instancia comprueba el alias PN/LID que faltaba, la misma respuesta (el mismo `response_id` y `event_id`) se vuelve a correlacionar y llega `interactive.response.updated` con `response_id`, `response_event_id` (el del evento original), `correlacion_anterior` y la respuesta con su correlación nueva; nunca un segundo `interactive.response`. Un clic en un enlace, una llamada, un código o un PIX nunca aparece: WhatsApp no lo informa.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "respuestas-interactivas",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Solo las que responden a este interactivo.",
            "explode": false,
            "in": "query",
            "name": "provider_id",
            "schema": {
              "description": "Solo las que responden a este interactivo.",
              "maxLength": 128,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "correlacion",
            "schema": {
              "enum": [
                "correlacionada",
                "accion_desconocida",
                "sin_mensaje",
                "otro_chat",
                "otro_autor",
                "no_respondible",
                "desconocida",
                ""
              ],
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limite",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "has_more": false,
                  "respuestas": [
                    {
                      "accion": {},
                      "autor": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "chat": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "correlacion": "correlacionada",
                      "event_id": "8a1d2c3e-0000-4000-8000-0000a08b063d",
                      "formato": "buttons_response",
                      "from_me": false,
                      "momento": "2026-10-24T15:08:12Z",
                      "provider_id": "PROVIDER_MESSAGE_ID",
                      "response_id": "8a1d2c3e-0000-4000-8000-00007baab4de"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RespuestasOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Las respuestas observadas a los interactivos",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/interactive/{provider_id}": {
      "get": {
        "description": "Scope `messages:read`. Cada observación por separado: `aceptacion` (pendiente, aceptado, rechazado, no_salio o desconocido si quedó ambiguo), `recibo` (no_observado, entregado o leido), `render` (siempre desconocido: el motor no puede saber si el teléfono lo mostró) y `respuesta` (observada solo con una respuesta real; no_observable si solo lleva copy, url, call o pix, cuyo clic WhatsApp no informa). El ACK del servidor no dice que el usuario lo vio ni que respondió. no garantizado en números no oficiales.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "seguimiento-interactivo",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El provider_id del mensaje.",
            "in": "path",
            "name": "provider_id",
            "required": true,
            "schema": {
              "description": "El provider_id del mensaje.",
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "acciones": [
                    {
                      "accion": "reply",
                      "titulo": "texto"
                    }
                  ],
                  "aceptacion": "pendiente",
                  "aviso": "texto",
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "recibo": "no_observado",
                  "render": "desconocido",
                  "respuesta": "no_observada",
                  "respuestas": [
                    "texto"
                  ],
                  "variante": "buttons",
                  "version": "texto"
                },
                "schema": {
                  "$ref": "#/components/schemas/SeguimientoInteractivo"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El seguimiento de un mensaje interactivo",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/labels": {
      "get": {
        "description": "Scope `labels:read`. Las etiquetas de WhatsApp del número (**no las del CRM**), en el orden de su ID, con cuántos chats y mensajes las tienen. En WhatsApp Business se ven con su color y en los mensajes; en un número normal son las Listas (sin color ni mensajes etiquetados a la vista). Pagina con `next_cursor`. Una eliminada solo sale con `incluir_eliminadas`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-etiquetas",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "incluir_eliminadas",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "has_more": false,
                  "labels": [
                    {
                      "actualizada_en": "2026-10-24T15:08:12Z",
                      "chats": 1,
                      "color": 1,
                      "eliminada": false,
                      "label_id": "3",
                      "mensajes": 1,
                      "nombre": "Ventas Centro"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/EtiquetasOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope labels:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Las etiquetas de WhatsApp del número",
        "tags": [
          "Etiquetas"
        ]
      },
      "post": {
        "description": "Scope `labels:manage`. Un comando durable (`label.edit` sin `label_id`): el motor trae primero las etiquetas del teléfono y elige el ID siguiente al mayor (no pisa una que ya existe); llega `label.created`. Funciona en WhatsApp Business y en un número normal (allí es una Lista: el color se guarda, pero ese cliente no lo muestra).\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `label.created`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "crear-etiqueta",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "color": 3,
                "nombre": "Pago pendiente"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEtiquetaNueva"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "label.edit",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope labels:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear una etiqueta de WhatsApp",
        "tags": [
          "Etiquetas"
        ]
      }
    },
    "/v1/instances/{id}/labels/{label_id}": {
      "delete": {
        "description": "Scope `labels:manage`. La elimina en WhatsApp (también de los chats y los mensajes que la tenían); llega `label.deleted`.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `label.deleted`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "eliminar-etiqueta",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El ID de la etiqueta en WhatsApp.",
            "in": "path",
            "name": "label_id",
            "required": true,
            "schema": {
              "description": "El ID de la etiqueta en WhatsApp.",
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "label.edit",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope labels:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Eliminar una etiqueta",
        "tags": [
          "Etiquetas"
        ]
      },
      "patch": {
        "description": "Scope `labels:manage`. Cambia el nombre o el color (lo que no se manda queda igual); llega `label.updated`.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `label.updated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "editar-etiqueta",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El ID de la etiqueta en WhatsApp.",
            "in": "path",
            "name": "label_id",
            "required": true,
            "schema": {
              "description": "El ID de la etiqueta en WhatsApp.",
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "color": 5,
                "nombre": "Pagado"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEtiquetaCambio"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "label.edit",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope labels:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Editar una etiqueta",
        "tags": [
          "Etiquetas"
        ]
      }
    },
    "/v1/instances/{id}/labels/{label_id}/associations": {
      "post": {
        "description": "Scope `labels:manage`. Un comando durable (`label.chat` o, con `objetivo`, `label.message`); llega `label.associated` o `label.dissociated`.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `label.associated` o `label.dissociated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "asociar-etiqueta",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El ID de la etiqueta en WhatsApp.",
            "in": "path",
            "name": "label_id",
            "required": true,
            "schema": {
              "description": "El ID de la etiqueta en WhatsApp.",
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "chat": {
                  "summary": "Chat",
                  "value": {
                    "asociar": true,
                    "destino": {
                      "jid": "CONTACTO@s.whatsapp.net"
                    }
                  }
                },
                "mensaje": {
                  "summary": "Mensaje",
                  "value": {
                    "asociar": true,
                    "destino": {
                      "jid": "CONTACTO@s.whatsapp.net"
                    },
                    "objetivo": {
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    }
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoAsociacion"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "label.chat",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope labels:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Poner o quitar una etiqueta de un chat o de un mensaje",
        "tags": [
          "Etiquetas"
        ]
      }
    },
    "/v1/instances/{id}/media/uploads": {
      "post": {
        "description": "Scope `media:write`. El cuerpo es el archivo crudo (no multipart ni base64) y `Content-Type` su MIME declarado. El motor lo copia en streaming al disco temporal (acotado por `multimedia.tamano_maximo_mb`), calcula su SHA-256, detecta el MIME REAL por el contenido (lo declarado no puede contradecirlo: 422 `mime_falso`), revisa la cuota de la instancia y de la app (429 `cuota_excedida`) y lo guarda en el bucket privado. Responde 201 con el `media_id` para `POST /v1/instances/{id}/messages` y un permiso temporal de descarga. Sin almacenamiento configurado, 503 `multimedia_deshabilitada`; con el disco casi lleno, 503 `presion_disco` con `Retry-After`. Los errores de multimedia traen su código en `type` (`urn:motor-whatsapp:error:<código>`).\n\n**Errores típicos:**\n\n- `400`: el cuerpo no se pudo leer.\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `413`: el archivo supera el tamaño máximo.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "subir-medio",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El MIME declarado (se compara con el contenido).",
            "in": "header",
            "name": "Content-Type",
            "schema": {
              "description": "El MIME declarado (se compara con el contenido).",
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Content-Length",
            "schema": {
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "El nombre del archivo (para un documento).",
            "explode": false,
            "in": "query",
            "name": "nombre",
            "schema": {
              "description": "El nombre del archivo (para un documento).",
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Opcional: el SHA-256 del archivo (hex). Si no coincide, 422.",
            "explode": false,
            "in": "query",
            "name": "sha256",
            "schema": {
              "description": "Opcional: el SHA-256 del archivo (hex). Si no coincide, 422.",
              "pattern": "^([0-9a-fA-F]{64})?$",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/octet-stream": {
              "schema": {
                "contentMediaType": "application/octet-stream",
                "format": "binary",
                "type": "string"
              }
            }
          },
          "description": "El archivo, crudo. `Content-Type` es el MIME declarado: el motor lo comprueba contra el contenido.",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "bytes": 48213,
                  "created_at": "2026-10-24T15:08:12Z",
                  "estado": "pendiente",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                  "metadatos": {},
                  "origen": "subida"
                },
                "schema": {
                  "$ref": "#/components/schemas/Medio"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Bad Request"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope media:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Request Entity Too Large"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Subir un archivo privado",
        "tags": [
          "Multimedia"
        ]
      }
    },
    "/v1/instances/{id}/messages": {
      "get": {
        "description": "Scope `messages:read`. Lo que el motor capturó (en vivo, importado del historial o enviado), del más nuevo al más viejo, con `next_cursor` estable y `has_more` exacto; filtros por chat, dirección, origen, operación y fechas. Un mensaje que llegó indescifrable y después legible (el reintento) sale una vez, legible; su `indescifrable` sale solo con `operacion=indescifrable`. El contenido sale del evento del ledger (`contenido_disponible: false` si su retención ya lo borró: `motivo_no_disponible: retencion`). Un mensaje temporal trae `vence_en` (su momento más `expiracion_seg`); al pasarlo, el motor borra su contenido y sus medios, sale con `contenido_disponible: false` y `motivo_no_disponible: vencido`, y emite `message.expired` una vez; en los mensajes que lo citan, la cita queda solo con `provider_id` y `citado_vencido: true`. **No es una búsqueda histórica de WhatsApp**: WhatsApp no la ofrece; lo que el motor no capturó no aparece.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-mensajes",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Solo los de ese chat (un peer_ref de esta instancia).",
            "explode": false,
            "in": "query",
            "name": "peer_ref",
            "schema": {
              "description": "Solo los de ese chat (un peer_ref de esta instancia).",
              "type": "string"
            }
          },
          {
            "description": "entrante o saliente.",
            "explode": false,
            "in": "query",
            "name": "direccion",
            "schema": {
              "description": "entrante o saliente.",
              "enum": [
                "entrante",
                "saliente",
                ""
              ],
              "type": "string"
            }
          },
          {
            "description": "live (en vivo), history (importado) u operator.",
            "explode": false,
            "in": "query",
            "name": "origen",
            "schema": {
              "description": "live (en vivo), history (importado) u operator.",
              "enum": [
                "live",
                "history",
                "operator",
                ""
              ],
              "type": "string"
            }
          },
          {
            "description": "De fábrica, todas.",
            "explode": false,
            "in": "query",
            "name": "operacion",
            "schema": {
              "description": "De fábrica, todas.",
              "enum": [
                "mensaje",
                "edicion",
                "revocacion",
                "reaccion",
                "indescifrable",
                ""
              ],
              "type": "string"
            }
          },
          {
            "description": "Desde esta fecha (incluida).",
            "explode": false,
            "in": "query",
            "name": "desde",
            "schema": {
              "description": "Desde esta fecha (incluida).",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Hasta esta fecha (excluida).",
            "explode": false,
            "in": "query",
            "name": "hasta",
            "schema": {
              "description": "Hasta esta fecha (excluida).",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "El next_cursor de la página anterior.",
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "description": "El next_cursor de la página anterior.",
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "has_more": false,
                  "mensajes": [
                    {
                      "chat": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "contenido_disponible": false,
                      "estado": "texto",
                      "from_me": false,
                      "message_ref": "8a1d2c3e-0000-4000-8000-0000992ae626",
                      "momento": "2026-10-24T15:08:12Z",
                      "operacion": "mensaje",
                      "origen": "live",
                      "provider_id": "PROVIDER_MESSAGE_ID",
                      "tipo_contenido": "texto"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/MensajesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los mensajes del store del motor (P053)",
        "tags": [
          "Mensajes"
        ]
      },
      "post": {
        "description": "Scope `messages:send`. `Idempotency-Key` obligatoria: repetir el pedido con la misma clave devuelve el MISMO comando (y el mismo `provider_message_id`); la misma clave con otro mensaje es 409. Responde 202 en cuanto el comando quedó guardado (`status: en_cola`). El resultado llega por eventos (`message.sent`, `command.failed`, `command.ambiguous`) y en `GET /v1/commands/{id}`: `enviado` (lo aceptó el servidor; entregado y leído llegan como `message.updated`), `fallido` con `error_code` y `stage`, o **`ambiguo`**: el mensaje pudo salir y no hubo respuesta; el motor **no lo reenvía** y lo concilia si llega su eco o un receipt. Si el ritmo de la instancia no deja enviarlo ya, **429 con el comando guardado** y `next_try` (no hace falta reintentar). Con la cola llena, 429 sin guardar. Una instancia bloqueada o reemplazada no acepta envíos (409). **Multimedia** (`tipo` image, video, document o audio): `medio.media_id` (una subida de esta instancia, lista y con un formato que sirve: 422 `formato_incompatible` si no; 404 `medio_no_encontrado` si no existe en esta instancia, aunque sea de otra) o `medio.url` (una URL cuyo host está en los destinos permitidos de los webhooks; el motor la importa como un trabajo durable y el envío espera a `media.ready`). `texto` es el caption (un audio no lleva). Nunca base64: sube el archivo primero. Va por el mismo outbox: el archivo se sube a WhatsApp antes de mandar el mensaje (si esa subida falla, no salió nada y se reintenta). Sin almacenamiento configurado, 503 `multimedia_deshabilitada`; el texto sigue igual. **Subtipos con conversión** (MW4b): `ptt` (nota de voz: Opus mono en Ogg, con su duración y forma de onda), `sticker` (WebP 512×512, estático hasta 100 KB o animado hasta 6 s y 500 KB), `ptv` (vídeo circular: MP4 cuadrado de 480, hasta 60 s) y `gif` (MP4 sin audio en bucle, hasta 30 s). El motor convierte el archivo como un trabajo durable con límites de procesos, tiempo y memoria; mientras tanto el comando sigue `en_cola` y `media.estado` es `pendiente`. Un archivo que no sirve para el subtipo es 422 `formato_no_convertible`; si la conversión falla, el envío falla con `conversion_fallida` y el motivo en `media.motivo` (`formato_no_convertible`, `tiempo_excedido`, `memoria_excedida`) y en `media.failed`. Nada de esto afecta al texto ni a otros envíos. `ptv` y `gif`: no garantizado en números no oficiales. **Tipos y operaciones de la MW5a**, por el mismo outbox: `location` (latitud, longitud, nombre y dirección), `contacts` (de 1 a 10; con teléfonos el motor arma la vCard, una vCard propia se valida: 422 `vcard_invalida`), `reaction` (`emoji` vacío la quita), `edit` (solo un texto propio, hasta 20 minutos después) y `revoke` (borrar para todos un mensaje propio, hasta 2 días y 12 horas) sobre un `objetivo` de ESTE chat; `forward` reenvía un mensaje recibido de cualquier chat de la instancia; `disappearing` fija el temporizador de mensajes efímeros del chat (en un chat con temporizador, los mensajes nuevos salen efímeros); `poll` (MW5b) manda una encuesta (su secreto de creación se guarda sellado: un reintento manda la misma; el resultado en `GET /v1/instances/{id}/polls/{provider_id}`); `interactive` (MW10) manda botones (`variante: buttons`: hasta 3 de responder, o hasta 2 entre copiar un código, abrir un enlace y llamar, o un solo PIX), una lista (`list`, con secciones y filas) o un carrusel (`carousel`, de 2 a 10 tarjetas con medio opcional): **no garantizado en números no oficiales**. No se rechaza por eso: sale y devuelve su resultado real (aceptado, rechazado o ambiguo); los límites se validan antes del outbox (422 `interactivo_invalido` con el campo). El seguimiento (aceptado, receipt y respuesta, por separado) en `GET /v1/instances/{id}/interactive/{provider_id}`; una respuesta llega como `interactive.response`. Un clic en un enlace, una llamada, un código copiado o un PIX nunca se infiere: WhatsApp no lo informa. **iOS no muestra las listas** (con un remitente normal dicen «no compatible»; con un Business, nada, aunque se entregan): con 3 opciones o menos conviene `buttons` con `reply`, y una lista puede llevar `respaldo_texto: true`, que manda después un texto con sus opciones numeradas y toma como su respuesta un número de esas opciones que conteste el mismo chat en 24 horas (`interactive.response` con `via: texto`, además del mensaje). Lo ajeno o fuera de la ventana es 422 tipificado (`mensaje_ajeno`, `fuera_de_ventana`, `no_editable`, `objetivo_desconocido`, `no_reenviable`) y también se revisa al salir (falla con `fuera_de_ventana` sin salir). Una **cita** tiene que ser un mensaje de este chat en esta instancia (si no, 422 `cita_ajena`). Un texto puede llevar `vista_previa` de un enlace que aparece en él: título, descripción y miniatura (`miniatura_media_id`, una imagen subida); el motor **no va a buscar la página** salvo con `obtener: true` y un host de los destinos permitidos (la misma allowlist y el control SSRF de los webhooks; si no, 422 `url_no_permitida`).\n\n**Asíncrona:** responde `202` con el comando en cola; sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo; después `message.sent` (lo aceptó el servidor de WhatsApp), `command.failed` o `command.ambiguous` (pudo salir: el motor no lo reenvía). Entregado y leído llegan como `message.updated`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: la `Idempotency-Key` ya se usó con otro mensaje, o la instancia está bloqueada o reemplazada.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: el ritmo de la instancia no deja enviarlo ya (el comando queda guardado, con `next_try`) o la cola está llena (no se guarda).\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "enviar-mensaje",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Obligatoria: hace el envío idempotente.",
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Obligatoria: hace el envío idempotente.",
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "audio": {
                  "summary": "Audio",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "tipo": "audio"
                  }
                },
                "borrar": {
                  "summary": "Borrar para todos",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "objetivo": {
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    },
                    "tipo": "revoke"
                  }
                },
                "botones": {
                  "summary": "Botones de respuesta (no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "botones": [
                        {
                          "accion": "reply",
                          "id": "confirmar-42",
                          "texto": "Sí, confirmo"
                        },
                        {
                          "accion": "reply",
                          "id": "cambiar-42",
                          "texto": "Cambiar fecha"
                        }
                      ],
                      "cuerpo": "¿Confirmas la entrega para mañana?",
                      "encabezado": "Tu pedido 42",
                      "pie": "Tienda Centro",
                      "variante": "buttons"
                    },
                    "tipo": "interactive"
                  }
                },
                "carrusel": {
                  "summary": "Carrusel con imágenes (no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "cuerpo": "Nuestros planes",
                      "tarjetas": [
                        {
                          "botones": [
                            {
                              "accion": "reply",
                              "id": "plan-basico",
                              "texto": "Lo quiero"
                            }
                          ],
                          "cuerpo": "Plan básico",
                          "medio": {
                            "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                          }
                        },
                        {
                          "botones": [
                            {
                              "accion": "reply",
                              "id": "plan-completo",
                              "texto": "Lo quiero"
                            },
                            {
                              "accion": "url",
                              "texto": "Detalles",
                              "url": "https://tienda.ejemplo.com/planes"
                            }
                          ],
                          "cuerpo": "Plan completo",
                          "medio": {
                            "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                          }
                        }
                      ],
                      "variante": "carousel"
                    },
                    "tipo": "interactive"
                  }
                },
                "contactos": {
                  "summary": "Contactos",
                  "value": {
                    "contactos": [
                      {
                        "nombre": "Soporte",
                        "telefonos": [
                          "+NUMERO_DE_SOPORTE"
                        ]
                      }
                    ],
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "tipo": "contacts"
                  }
                },
                "cta": {
                  "summary": "Copiar un código, abrir un enlace y llamar (no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "botones": [
                        {
                          "accion": "copy",
                          "codigo": "DESC10",
                          "texto": "Copiar cupón"
                        },
                        {
                          "accion": "url",
                          "texto": "Ver la tienda",
                          "url": "https://tienda.ejemplo.com/ofertas"
                        }
                      ],
                      "cuerpo": "Tu cupón de descuento",
                      "variante": "buttons"
                    },
                    "tipo": "interactive"
                  }
                },
                "documento": {
                  "summary": "Documento (PDF)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                      "nombre_archivo": "factura-0042.pdf"
                    },
                    "tipo": "document"
                  }
                },
                "editar": {
                  "summary": "Editar un texto propio",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "objetivo": {
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    },
                    "texto": "Texto corregido",
                    "tipo": "edit"
                  }
                },
                "encuesta": {
                  "summary": "Encuesta",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "opciones": [
                      "Lunes",
                      "Miércoles",
                      "Viernes"
                    ],
                    "pregunta": "¿Qué día te queda mejor?",
                    "tipo": "poll"
                  }
                },
                "enlace": {
                  "summary": "Texto con vista previa de un enlace",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "texto": "Mira el pedido: https://tienda.ejemplo.com/pedidos/42",
                    "vista_previa": {
                      "descripcion": "Sale hoy",
                      "miniatura_media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                      "titulo": "Pedido 42",
                      "url": "https://tienda.ejemplo.com/pedidos/42"
                    }
                  }
                },
                "gif": {
                  "summary": "GIF (un MP4 en bucle, no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "texto": "jaja",
                    "tipo": "gif"
                  }
                },
                "imagen": {
                  "summary": "Imagen con caption",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "texto": "Tu comprobante",
                    "tipo": "image"
                  }
                },
                "lista": {
                  "summary": "Lista con respaldo de texto (iOS no muestra las listas; no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "boton_lista": "Ver horarios",
                      "cuerpo": "Elige un horario para tu cita",
                      "encabezado": "Horarios",
                      "respaldo_texto": true,
                      "secciones": [
                        {
                          "filas": [
                            {
                              "descripcion": "Sede Centro",
                              "id": "h-0900",
                              "titulo": "09:00"
                            },
                            {
                              "id": "h-1100",
                              "titulo": "11:00"
                            }
                          ],
                          "titulo": "Mañana"
                        },
                        {
                          "filas": [
                            {
                              "id": "h-1600",
                              "titulo": "16:00"
                            }
                          ],
                          "titulo": "Tarde"
                        }
                      ],
                      "variante": "list"
                    },
                    "tipo": "interactive"
                  }
                },
                "llamar": {
                  "summary": "Botón para llamar (abre el marcador; no es una llamada del motor)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "botones": [
                        {
                          "accion": "call",
                          "telefono": "+NUMERO_DE_SOPORTE",
                          "texto": "Llamar"
                        }
                      ],
                      "cuerpo": "¿Prefieres hablar con alguien?",
                      "variante": "buttons"
                    },
                    "tipo": "interactive"
                  }
                },
                "nota_de_voz": {
                  "summary": "Nota de voz (ptt: se convierte a Opus)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "tipo": "ptt"
                  }
                },
                "pix": {
                  "summary": "PIX (información de pago, no es una pasarela)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "interactivo": {
                      "botones": [
                        {
                          "accion": "pix",
                          "pix": {
                            "clave": "pagos@tienda.ejemplo.com",
                            "comercio": "Tienda Centro",
                            "tipo_clave": "email"
                          }
                        }
                      ],
                      "cuerpo": "Paga tu pedido 42 con PIX",
                      "variante": "buttons"
                    },
                    "tipo": "interactive"
                  }
                },
                "ptv": {
                  "summary": "Vídeo circular (ptv, no garantizado en números no oficiales)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "tipo": "ptv"
                  }
                },
                "reaccion": {
                  "summary": "Reaccionar",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "emoji": "👍",
                    "objetivo": {
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    },
                    "tipo": "reaction"
                  }
                },
                "reenviar": {
                  "summary": "Reenviar un mensaje recibido",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "objetivo": {
                      "provider_id": "PROVIDER_MESSAGE_ID"
                    },
                    "tipo": "forward"
                  }
                },
                "sticker": {
                  "summary": "Sticker (de una imagen, un GIF o un vídeo: WebP 512×512)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "tipo": "sticker"
                  }
                },
                "temporizador": {
                  "summary": "Mensajes efímeros (7 días)",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "segundos": 604800,
                    "tipo": "disappearing"
                  }
                },
                "texto": {
                  "summary": "Texto",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "texto": "Hola, tu pedido salió hoy."
                  }
                },
                "ubicacion": {
                  "summary": "Ubicación",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "tipo": "location",
                    "ubicacion": {
                      "direccion": "Av. Principal 123",
                      "latitud": -12.0464,
                      "longitud": -77.0428,
                      "nombre": "Tienda Centro"
                    }
                  }
                },
                "video_url": {
                  "summary": "Vídeo desde una URL permitida",
                  "value": {
                    "destino": {
                      "telefono": "+NUMERO_DEL_CONTACTO"
                    },
                    "medio": {
                      "url": "https://archivos.ejemplo.com/videos/demo.mp4"
                    },
                    "texto": "Así funciona",
                    "tipo": "video"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoMensaje"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "en_cola",
                  "type": "message.text",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:send.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Enviar un mensaje",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/messages/{message_ref}": {
      "get": {
        "description": "Scope `messages:read`. El mensaje, su estado (solo sube: enviado, entregado, leído, reproducido) y los receipts de cada destinatario (en un grupo, cada participante).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-mensaje",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El message_ref de la consulta.",
            "in": "path",
            "name": "message_ref",
            "required": true,
            "schema": {
              "description": "El message_ref de la consulta.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "mensaje": {
                    "chat": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "contenido_disponible": false,
                    "estado": "texto",
                    "from_me": false,
                    "message_ref": "8a1d2c3e-0000-4000-8000-0000992ae626",
                    "momento": "2026-10-24T15:08:12Z",
                    "operacion": "mensaje",
                    "origen": "live",
                    "provider_id": "PROVIDER_MESSAGE_ID",
                    "tipo_contenido": "texto"
                  },
                  "recibos": [
                    {
                      "destinatario": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "momento": "2026-10-24T15:08:12Z",
                      "tipo": "message.received"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/MensajeOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Un mensaje del store y su estado por destinatario",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/messages/{provider_id}/receipts": {
      "get": {
        "description": "Scope `messages:read`. Entregado, leído y reproducido de cada destinatario (en un grupo, de cada participante), con su momento. **Un receipt que no llegó puede no llegar nunca**: depende de la privacidad del otro (confirmaciones de lectura) y de su teléfono; el motor nunca lo inventa.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "recibos-mensaje",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El provider_id del mensaje.",
            "in": "path",
            "name": "provider_id",
            "required": true,
            "schema": {
              "description": "El provider_id del mensaje.",
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "recibos": [
                    {
                      "destinatario": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "momento": "2026-10-24T15:08:12Z",
                      "tipo": "entregado"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RecibosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los receipts de un mensaje propio, por destinatario y tipo",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/newsletters": {
      "get": {
        "description": "Scope `newsletters:read`. Los canales que el número sigue o administra según lo último que dijo WhatsApp (la proyección de esta instancia: el mismo canal en otro número es otra fila), con su `rol` (owner y admin publican), si lo sigue y si está silenciado, con `next_cursor` y `has_more`. Con `actualizar=true` el motor pide antes la lista a WhatsApp (los que ya no están quedan `siguiendo: false`).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-canales",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Primero pide la lista a WhatsApp (409 no_conectada sin conexión).",
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "description": "Primero pide la lista a WhatsApp (409 no_conectada sin conexión).",
              "type": "boolean"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "canales": [
                    {
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "canal": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "descripcion": "Descripción de ejemplo",
                      "en_vivo": false,
                      "nombre": "Ventas Centro",
                      "rol": "owner",
                      "siguiendo": false,
                      "silenciado": false,
                      "suscriptores": 1,
                      "verificado": false,
                      "version": 1
                    }
                  ],
                  "has_more": false
                },
                "schema": {
                  "$ref": "#/components/schemas/CanalesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los canales del número (P080)",
        "tags": [
          "Canales"
        ]
      },
      "post": {
        "description": "Scope `newsletters:write`. `newsletter.create`: el `result` trae el JID del canal y su enlace. Si el proceso cae a mitad o el servidor no contesta, el comando queda `ambiguo` (`resultado_incierto`): nunca se crea dos veces a ciegas. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "crear-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "descripcion": "Ofertas y avisos de la tienda",
                "nombre": "Novedades Centro"
              },
              "schema": {
                "$ref": "#/components/schemas/CrearCanal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.create",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear un canal (P079)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/follow": {
      "post": {
        "description": "Scope `newsletters:write`. `newsletter.follow` con el `jid` del canal o su `enlace`: el `result` trae el JID; el canal queda `siguiendo` con el rol que diga WhatsApp. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "seguir-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "enlace": {
                  "summary": "Enlace",
                  "value": {
                    "canal": {
                      "enlace": "https://whatsapp.com/channel/CODIGO_DEL_CANAL"
                    }
                  }
                },
                "jid": {
                  "summary": "Jid",
                  "value": {
                    "canal": {
                      "jid": "CANAL@newsletter"
                    }
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/Seguir-canalRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.follow",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Seguir un canal (P082)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/invite/info": {
      "post": {
        "description": "Scope `newsletters:read`. Lo que WhatsApp dice del canal de un enlace (nombre, suscriptores, verificación). Uno que no existe es 404 `canal_no_encontrado`; sin conexión, 409.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "info-invitacion-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "enlace": "https://whatsapp.com/channel/CODIGO_DEL_CANAL"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEnlaceCanal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "jid": "CONTACTO@s.whatsapp.net",
                  "nombre": "Ventas Centro",
                  "suscriptores": 1,
                  "verificado": false
                },
                "schema": {
                  "$ref": "#/components/schemas/CanalInvitacion"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Consultar un enlace de canal sin seguirlo (P081)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}": {
      "get": {
        "description": "Scope `newsletters:read`. Su nombre, descripción, enlace de invitación, estado, verificación, suscriptores y el rol del número. Con `actualizar=true` el motor lo consulta antes a WhatsApp.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "canal": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "canal": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "descripcion": "Descripción de ejemplo",
                    "en_vivo": false,
                    "nombre": "Ventas Centro",
                    "rol": "owner",
                    "siguiendo": false,
                    "silenciado": false,
                    "suscriptores": 1,
                    "verificado": false,
                    "version": 1
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/CanalOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Un canal (P081)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/live": {
      "post": {
        "description": "Scope `newsletters:read`. WhatsApp manda en vivo las vistas y reacciones por un rato (el que diga el servidor, en `en_vivo_hasta`); llegan como `newsletter.updates`. Hay que volver a pedirlo cuando vence.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "en-vivo-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "en_vivo_hasta": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/EnVivoOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Recibir en vivo las vistas y reacciones de un canal (P084)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/messages": {
      "get": {
        "description": "Scope `newsletters:read`. Las publicaciones que el motor conoce, de la más nueva a la más vieja, cada una con su **`server_id`** (el ID que asigna WhatsApp: lo usan las vistas, las reacciones y las actualizaciones) y su **`provider_id`** (el ID de mensaje) por separado: no se confunden. Con `actualizar=true` el motor pide antes a WhatsApp `cantidad` publicaciones (anteriores a `antes`) y guarda sus contadores: una consulta repetida no duplica nada. El archivo de una publicación consultada no se descarga.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "publicaciones-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "description": "Primero pide a WhatsApp las publicaciones (cantidad, anteriores a antes) y guarda sus contadores.",
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "description": "Primero pide a WhatsApp las publicaciones (cantidad, anteriores a antes) y guarda sus contadores.",
              "type": "boolean"
            }
          },
          {
            "description": "Con actualizar: cuántas pedir al servidor.",
            "explode": false,
            "in": "query",
            "name": "cantidad",
            "schema": {
              "default": 20,
              "description": "Con actualizar: cuántas pedir al servidor.",
              "format": "int64",
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Las anteriores a este server_id (la página siguiente).",
            "explode": false,
            "in": "query",
            "name": "antes",
            "schema": {
              "description": "Las anteriores a este server_id (la página siguiente).",
              "format": "int64",
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "has_more": false,
                  "publicaciones": [
                    {
                      "direccion": "entrante",
                      "momento": "2026-10-24T15:08:12Z",
                      "reacciones": {},
                      "server_id": 125,
                      "tipo": "message.received",
                      "version": 1,
                      "vistas": 1,
                      "visto": false
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/PublicacionesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Las publicaciones de un canal (P083)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/mute": {
      "put": {
        "description": "Scope `newsletters:write`. `newsletter.mute`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "silenciar-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "silenciar": true
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoSilenciarCanal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.mute",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Silenciar o reactivar un canal (P084)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/reaction": {
      "post": {
        "description": "Scope `newsletters:write`. `newsletter.reaction` sobre el **server_id** de la publicación (`emoji` vacío la quita); el ID de la reacción lo fija el motor por comando (un reintento manda la misma). Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "reaccion-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "emoji": "👍",
                "server_id": 125
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoReaccionCanal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.reaction",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Reaccionar a una publicación (P084)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/unfollow": {
      "post": {
        "description": "Scope `newsletters:write`. `newsletter.follow` con `seguir: false`: el canal queda `siguiendo: false`. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "dejar-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.follow",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Dejar de seguir un canal (P082)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/updates": {
      "post": {
        "description": "Scope `newsletters:read`. El motor pide a WhatsApp las actualizaciones (desde un momento o después de un `server_id`) y las aplica con «última escritura gana»: lo que cambió deja `newsletter.updates`; una repetida, nada.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "actualizaciones-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "despues_de": 120
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoActualizaciones"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "recibidas": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/ActualizacionesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Traer las vistas y reacciones de un canal (P083)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/newsletters/{canal_ref}/view": {
      "post": {
        "description": "Scope `newsletters:write`. `newsletter.view` con los **server_id** (no los ID de mensaje): suma a su contador de vistas. No es «leído» en los otros dispositivos del número. Un comando durable: el resultado en `GET /v1/commands/{id}` (su `result` trae lo que devolvió WhatsApp) y los eventos `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed` con su `command_id`. Los permisos los decide WhatsApp: un rechazo falla con su error real (`sin_permiso`, `canal_no_encontrado`, `rechazado_por_whatsapp`). Sin conexión vuelve a la cola con su backoff.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `newsletter.joined`, `newsletter.left`, `newsletter.muted` o `newsletter.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-publicaciones-canal",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El peer_ref del canal en esta instancia.",
            "in": "path",
            "name": "canal_ref",
            "required": true,
            "schema": {
              "description": "El peer_ref del canal en esta instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "server_ids": [
                  124,
                  125
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoVerCanal"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "newsletter.view",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope newsletters:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Marcar publicaciones como vistas (P084)",
        "tags": [
          "Canales"
        ]
      }
    },
    "/v1/instances/{id}/pairing": {
      "get": {
        "description": "Scope `instances:pair`. `reto` es null si no hay uno vigente. `reto.valor` es el texto crudo del QR (dibújalo; no es una imagen), el código de 8 caracteres, las opciones WebAuthn (JSON) cuando WhatsApp exige una passkey, o el código a comparar con el teléfono. Es sensible: no lo guardes ni lo registres. Respuesta `Cache-Control: no-store`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-emparejamiento",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "creado_en": "2026-10-24T15:08:12Z",
                  "fase": "texto",
                  "generacion": 1,
                  "modo": "qr",
                  "reto": {
                    "expira_en": "2026-10-24T15:08:12Z",
                    "tipo": "qr",
                    "valor": "texto"
                  },
                  "terminado_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Emparejamiento"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:pair.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Consultar el reto vigente y su vencimiento",
        "tags": [
          "Instancias"
        ]
      },
      "post": {
        "description": "Scope `instances:pair`. Responde 202 en cuanto el intento quedó guardado; el reto (QR o código) se consulta con `GET /v1/instances/{id}/pairing`. Cada pedido abre una generación nueva y reemplaza el intento anterior sin desvincular nada: un QR vencido se resuelve pidiendo otro.\n\n**Asíncrona:** no es un comando: responde `202` en cuanto el intento quedó guardado. Consulta el reto en `GET /v1/instances/{id}/pairing` cuando llegue `pairing.available`; después llegan `paired` y `connected` (o `pairing.expired` o `pairing.failed`) y cada cambio de estado como `state.changed`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: la instancia ya está vinculada o archivada, o `generacion_esperada` no coincide.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "emparejar-instancia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "codigo": {
                  "summary": "Codigo",
                  "value": {
                    "modo": "codigo",
                    "telefono": "+NUMERO_DE_TU_TELEFONO"
                  }
                },
                "qr": {
                  "summary": "Qr",
                  "value": {
                    "modo": "qr"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEmparejar"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "estado": "texto",
                  "fase": "texto",
                  "generacion": 1,
                  "instancia_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "modo": "qr"
                },
                "schema": {
                  "$ref": "#/components/schemas/IntentoAceptado"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:pair.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Iniciar el emparejamiento (QR o código)",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/pairing/passkey": {
      "post": {
        "description": "Scope `instances:pair`. Solo cuando el reto es `passkey`. La respuesta tiene que venir de un autenticador válido para el origen de WhatsApp: el motor no la fabrica ni la valida por su cuenta. Después llega un reto `passkey_confirmacion`.\n\n**Asíncrona:** responde `202` cuando el motor pasó la respuesta a WhatsApp; el siguiente reto (`passkey_confirmacion`) llega como `pairing.available`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "responder-passkey",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "generacion": 2,
                "respuesta": {
                  "id": "ID_DE_LA_CREDENCIAL",
                  "rawId": "ID_DE_LA_CREDENCIAL",
                  "response": {
                    "authenticatorData": "BASE64URL",
                    "clientDataJSON": "BASE64URL",
                    "signature": "BASE64URL"
                  },
                  "type": "public-key"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/Responder-passkeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "aceptado": false
                },
                "schema": {
                  "$ref": "#/components/schemas/AceptadoOutputBody"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:pair.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Mandar la respuesta WebAuthn (experimental)",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/pairing/passkey/confirm": {
      "post": {
        "description": "Scope `instances:pair`. Solo cuando el reto es `passkey_confirmacion` y la persona comprobó que el código coincide.\n\n**Asíncrona:** responde `202`; al completarse la vinculación llegan `paired`, `connected` y `state.changed`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "confirmar-passkey",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "generacion": 2
              },
              "schema": {
                "$ref": "#/components/schemas/Confirmar-passkeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "aceptado": false
                },
                "schema": {
                  "$ref": "#/components/schemas/AceptadoOutputBody"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:pair.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Confirmar que el código coincide con el del teléfono (experimental)",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/polls/{provider_id}": {
      "get": {
        "description": "Scope `messages:read`. El voto vigente de cada votante (un cambio de voto reemplaza el anterior), contado por opción. Los votos que no se pudieron descifrar se cuentan aparte (`sin_descifrar`): nunca se inventa una opción. Cada voto llega también como `poll.vote` con el resultado.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "resultado-encuesta",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "El provider_id del mensaje.",
            "in": "path",
            "name": "provider_id",
            "required": true,
            "schema": {
              "description": "El provider_id del mensaje.",
              "maxLength": 128,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "conocida": false,
                  "opciones": [
                    {
                      "opcion": "texto",
                      "votos": 1
                    }
                  ],
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "seleccionables": 1,
                  "sin_descifrar": 1,
                  "votantes": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/ResultadoEncuesta"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El resultado agregado de una encuesta",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/presence": {
      "post": {
        "description": "Scope `presence:write`. Se manda en el momento por la sesión conectada (sin cola; si no está conectada, 409 `no_conectada`). Para recibir la presencia de otros, WhatsApp exige estar «en línea».\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "presencia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "disponible": true
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoPresencia"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope presence:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "En línea o fuera de línea",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/presence-subscriptions": {
      "get": {
        "description": "Las suscripciones de presencia de la instancia: a quién sigues, desde cuándo, hasta cuándo y si sigue vigente (`vigente: false` pasado su TTL), con la última presencia que llegó de cada contacto mientras estaba vigente (en línea, última vez, escribiendo o grabando).\n\n**Scope:** `presence:write`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-presencias",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "suscripciones": [
                    {
                      "contacto": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "creada_en": "2026-10-24T15:08:12Z",
                      "vence_en": "2026-10-24T15:08:12Z",
                      "vigente": false
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/PresenciasOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La presencia que se sigue",
        "tags": [
          "Mensajes"
        ]
      },
      "post": {
        "description": "Scope `presence:write`. Mientras la suscripción está vigente, cada cambio llega como `presence` (en línea, fuera de línea con la última vez si el contacto la comparte, escribiendo, grabando). Pasado su TTL caduca sola: no llegan más eventos y la última presencia deja de mostrarse. Repetirla la renueva. Se vuelve a pedir en cada reconexión.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "suscribir-presencia",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destino": {
                  "jid": "CONTACTO@s.whatsapp.net"
                },
                "ttl_seg": 3600
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoSuscripcionPresencia"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "contacto": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "creada_en": "2026-10-24T15:08:12Z",
                  "vence_en": "2026-10-24T15:08:12Z",
                  "vigente": false
                },
                "schema": {
                  "$ref": "#/components/schemas/SuscripcionPresencia"
                }
              }
            },
            "description": "Created"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope presence:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Seguir la presencia de un contacto (con TTL)",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/privacy": {
      "get": {
        "description": "Scope `privacy:read`. La privacidad (las opciones del SDK), el temporizador por defecto (el último que fijó el motor) y cuántos contactos están bloqueados (la lista: `GET …/blocklist`). Con `actualizar=true` el motor la consulta antes al servidor.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-privacidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {},
                "schema": {
                  "$ref": "#/components/schemas/PerfilV1"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope privacy:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La privacidad del número y sus bloqueos",
        "tags": [
          "Perfil y privacidad"
        ]
      },
      "put": {
        "description": "Scope `privacy:write`. `privacy.set`: el servidor devuelve la privacidad completa, que queda confirmada, con `privacy.changed`. Las opciones son las del SDK, con sus valores: `groupadd` (quién te agrega a grupos), `last` (última vez), `status` (estados) y `profile` (foto): all, contacts, contact_blacklist, none; `readreceipts`: all, none; `online`: all, match_last_seen; `calladd`: all, known; `messages`: all, contacts; `defense`: on_standard, off; `stickers`: contacts, contact_allowlist, none. Las listas de contact_blacklist y contact_allowlist se editan en el teléfono.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `privacy.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cambiar-privacidad",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "opcion": "last",
                "valor": "contacts"
              },
              "schema": {
                "$ref": "#/components/schemas/CambioPrivacidad"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "privacy.set",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope privacy:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar una opción de privacidad",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/privacy/disappearing": {
      "put": {
        "description": "Scope `privacy:write`. `privacy.disappearing`: 0, 24 horas, 7 días o 90 días para los chats nuevos (cada chat sigue con el suyo: `message.disappearing`). El SDK no tiene cómo leerlo: el motor muestra el último que fijó y `privacy.changed` lo dice.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `privacy.changed`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "temporizador-por-defecto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "segundos": 604800
              },
              "schema": {
                "$ref": "#/components/schemas/TemporizadorPorDefecto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "privacy.disappearing",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope privacy:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El temporizador por defecto de los chats nuevos",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/profile": {
      "get": {
        "description": "Scopes `profile:read` y/o `privacy:read`: cada uno ve solo lo suyo. Con `profile:read`, el nombre visible, el recado y el ID de la foto (cada uno con quién lo fijó y si WhatsApp lo confirmó); con `privacy:read`, la privacidad, el temporizador por defecto (el último conocido: el SDK no lo puede consultar) y cuántos contactos están bloqueados. Con `actualizar=true` el motor consulta antes al servidor lo que la key puede leer (409 `no_conectada` sin conexión).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-perfil",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "actualizar",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {},
                "schema": {
                  "$ref": "#/components/schemas/PerfilV1"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope profile:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "El perfil propio del número, su privacidad y sus bloqueos",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/profile/about": {
      "put": {
        "description": "Scope `profile:write`. `profile.about`. El «Info» que muestran los teléfonos es el text status de WhatsApp: el motor lo escribe como WhatsApp Web (la mutación `xwa2_update_text_status`, que tiene que confirmar el servidor, y después el estado viejo), con la forma de Ajustes `perfil.forma_info` (de fábrica, `24h`: se ve 24 horas), fijada al aceptar el comando: un cambio del ajuste no cambia uno en cola, y el largo se valida con esa forma. El `result` del comando dice por qué vía salió (`via`), con qué duración (`duracion_seg`) y qué pasó con el estado viejo (`clasico`). Un comando durable: el resultado en `GET /v1/commands/{id}` y `profile.updated` (con `command_id`). Lo que pide el motor queda `confirmado: false` hasta que WhatsApp dice lo mismo (un evento o la consulta que el motor hace después del cambio). Sin conexión vuelve a la cola con su backoff; un rechazo del servidor es `fallido` con su código.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `profile.updated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cambiar-recado",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "texto": "Atención de 9:00 a 18:00"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoRecado"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "profile.about",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope profile:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar el recado («info») del número",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/profile/name": {
      "put": {
        "description": "Scope `profile:write`. `profile.name`, por el appstate (el eco confirma). Un comando durable: el resultado en `GET /v1/commands/{id}` y `profile.updated` (con `command_id`). Lo que pide el motor queda `confirmado: false` hasta que WhatsApp dice lo mismo (un evento o la consulta que el motor hace después del cambio). Sin conexión vuelve a la cola con su backoff; un rechazo del servidor es `fallido` con su código.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `profile.updated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "cambiar-nombre",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "nombre": "Tienda Centro"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoNombre"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "profile.name",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope profile:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar el nombre visible del número",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/profile/picture": {
      "delete": {
        "description": "Scope `profile:write`. `profile.picture` con `quitar`. **Experimental: no garantizado en números no oficiales.** Un comando durable: el resultado en `GET /v1/commands/{id}` y `profile.updated` (con `command_id`). Lo que pide el motor queda `confirmado: false` hasta que WhatsApp dice lo mismo (un evento o la consulta que el motor hace después del cambio). Sin conexión vuelve a la cola con su backoff; un rechazo del servidor es `fallido` con su código.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `profile.updated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "quitar-foto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "profile.picture",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope profile:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Quitar la foto del número (experimental)",
        "tags": [
          "Perfil y privacidad"
        ]
      },
      "put": {
        "description": "Scope `profile:write`. `profile.picture` con un JPEG subido a esta instancia (hasta 2 MB, de 192 a 2048 píxeles por lado; si no, 422 `foto_invalida`). WhatsApp solo acepta 640 × 640: el motor la recorta al centro y la deja en esa medida. El SDK no tiene un método para la foto propia: el motor manda el IQ de WhatsApp Web sin destino y devuelve el resultado real (`foto_invalida` si el servidor rechaza la imagen). **Experimental: no garantizado en números no oficiales.** Un comando durable: el resultado en `GET /v1/commands/{id}` y `profile.updated` (con `command_id`). Lo que pide el motor queda `confirmado: false` hasta que WhatsApp dice lo mismo (un evento o la consulta que el motor hace después del cambio). Sin conexión vuelve a la cola con su backoff; un rechazo del servidor es `fallido` con su código.\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `profile.updated`, con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "cambiar-foto",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoFoto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "profile.picture",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope profile:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar la foto del número (experimental)",
        "tags": [
          "Perfil y privacidad"
        ]
      }
    },
    "/v1/instances/{id}/proxy": {
      "put": {
        "description": "Scope `instances:manage`. `proxy_id` es uno de `GET /v1/proxies`; null la deja directa. Vale desde la próxima conexión (`reconnect`).\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "v1-proxy-instancia",
        "parameters": [
          {
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "proxy_id": "8a1d2c3e-0000-4000-8000-0000000000e1"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoProxyInstancia"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "archivada_en": "2026-10-24T15:08:12Z",
                  "bloqueada_hasta": "2026-10-24T15:08:12Z",
                  "caida_desde": "2026-10-24T15:08:12Z",
                  "canario": false,
                  "checked_at": "2026-10-24T15:08:12Z",
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "conectada_en": "2026-10-24T15:08:12Z",
                  "config": {
                    "reconexion_automatica": false
                  },
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "conectado",
                  "estado_deseado": "activo",
                  "generacion": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "motivo": "",
                  "nombre": "Ventas Centro",
                  "numero": "+NUMERO_DE_TU_TELEFONO",
                  "owner_ref": "empresa-42",
                  "proveedor": "whatsmeow",
                  "proximo_intento_en": "2026-10-24T15:08:12Z",
                  "proxy_id": "8a1d2c3e-0000-4000-8000-0000c9e41541",
                  "reconexiones": 1,
                  "ultimo_error": "",
                  "ultimo_error_en": "2026-10-24T15:08:12Z",
                  "version": 1,
                  "vinculada_en": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Instancia"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Asignar el proxy de una instancia",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/instances/{id}/read": {
      "post": {
        "description": "Scope `messages:send`. Un comando durable (`chat.read` o, con `reproducido`, `chat.played`): por chat, por `provider_ids` o todo hasta un momento (`hasta`); en un grupo, un receipt por remitente. **Reproducido es distinto de leído** (notas de voz y vídeos; otro tipo es `fallido` con `no_reproducible`). Al completarse, los mensajes suben a `leido`/`reproducido` (`message.updated`). Ojo: el otro solo ve el leído si los dos tienen las confirmaciones de lectura activadas (privacidad de WhatsApp).\n\n**Asíncrona:** responde `202` con el comando guardado (`status: aceptado` o `en_cola`); sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo y, si falla, `command.failed` (o `command.ambiguous` si pudo tener efecto). El efecto llega como `message.updated` (los mensajes suben a `leido` o `reproducido`), con el `command_id` en el sobre.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "marcar-leido",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destino": {
                  "jid": "CONTACTO@s.whatsapp.net"
                },
                "provider_ids": [
                  "PROVIDER_MESSAGE_ID"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoLectura"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "aceptado",
                  "type": "chat.read",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope messages:send.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Marcar mensajes recibidos como leídos o reproducidos",
        "tags": [
          "Mensajes"
        ]
      }
    },
    "/v1/instances/{id}/status": {
      "get": {
        "description": "Scope `status:read`. Los status recibidos de tus contactos (`entrante`) y los del número (`saliente`), los más nuevos primero, con `next_cursor` y `has_more`. Solo los que el motor todavía retiene: un status se guarda hasta `retener_hasta` (Ajustes, nunca más que su vencimiento en WhatsApp a las 24 horas); después se borra y el contenido de su `status.received` queda redactado. Uno que su autor borró queda `revocado`, sin contenido (`status.revoked`). El archivo de un status recibido no se descarga: solo su tipo, su MIME y su caption.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "listar-status",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "entrante (los de tus contactos) o saliente (los del número).",
            "explode": false,
            "in": "query",
            "name": "direccion",
            "schema": {
              "description": "entrante (los de tus contactos) o saliente (los del número).",
              "enum": [
                "entrante",
                "saliente",
                ""
              ],
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "cursor",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "format": "int64",
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "estados": [
                    {
                      "direccion": "entrante",
                      "momento": "2026-10-24T15:08:12Z",
                      "provider_id": "PROVIDER_MESSAGE_ID",
                      "retener_hasta": "2026-10-24T15:08:12Z",
                      "revocado": false,
                      "status_id": "8a1d2c3e-0000-4000-8000-0000bbefc4cd",
                      "tipo": "message.received",
                      "vence_en": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "has_more": false
                },
                "schema": {
                  "$ref": "#/components/schemas/EstadosOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope status:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los status que la instancia retiene",
        "tags": [
          "Status"
        ]
      },
      "post": {
        "description": "Scope `status:write`. **Experimental** (upstream lo anuncia así: las audiencias grandes pueden fallar; no garantizado en números no oficiales). Va por el mismo outbox que un mensaje: `Idempotency-Key` obligatoria, 202 con el comando guardado y el resultado real en eventos y en `GET /v1/commands/{id}`: `enviado`, `fallido` (rechazado por WhatsApp, o la audiencia no se cumple: nada salió) o `ambiguo` (pudo salir sin respuesta: no se reenvía). **La audiencia es explícita**: `modo: privacidad` es la privacidad de status del número (la del teléfono: `contacts`, `allowlist` o `denylist`), que tienes que declarar en `privacidad` (si es otra, falla `privacidad_distinta`; si WhatsApp informa una que el motor no conoce, falla `privacidad_desconocida`); `modo: lista` son solo esos destinos, que tienen que estar dentro de esa privacidad (si no, falla `fuera_de_privacidad`). En los dos, `max_destinatarios` es lo más que aceptas (si la audiencia tiene más, falla `audiencia_excedida`; no puede pasar el de Ajustes). Quien no tiene dispositivos (no usa WhatsApp) queda **omitido**, y quien no recibió su copia cifrada en ningún dispositivo (sin sesión ni prekeys utilizables) queda en `sin_cifrar` y no cuenta como destinatario: el `result` dice `destinatarios`, `omitidos`, `sin_cifrar`, `parcial`, `privacidad`, `audiencia_conocida` y `vence_en` (24 horas). Un status ambiguo que WhatsApp confirma después (su eco o un receipt) pasa a `enviado` con su `vence_en`; si su audiencia no se conoce, `audiencia_conocida` es `false` y no hay `destinatarios`. Sin nadie a quien mandarlo, falla `sin_destinatarios`; si no se pudo cifrar para nadie, `sin_cifrar` (en los dos, nada salió). No es una herramienta de campañas.\n\n**Asíncrona:** responde `202` con el comando en cola; sigue su estado en `GET /v1/commands/{id}`. Llega `command.accepted` al aceptarlo; después `message.sent` (lo aceptó el servidor de WhatsApp), `command.failed` o `command.ambiguous` (pudo salir: el motor no lo reenvía). Entregado y leído llegan como `message.updated`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `429`: llegaste a un límite (ritmo, cuota o cupo); respeta `Retry-After` si viene.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "publicar-status",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          },
          {
            "description": "Obligatoria: hace la publicación idempotente.",
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Obligatoria: hace la publicación idempotente.",
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "imagen_lista": {
                  "summary": "Imagen lista",
                  "value": {
                    "audiencia": {
                      "destinos": [
                        {
                          "telefono": "+NUMERO_DEL_CONTACTO"
                        }
                      ],
                      "max_destinatarios": 10,
                      "modo": "lista"
                    },
                    "medio": {
                      "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1"
                    },
                    "texto": "Nuevo catálogo",
                    "tipo": "image"
                  }
                },
                "texto": {
                  "summary": "Texto",
                  "value": {
                    "audiencia": {
                      "max_destinatarios": 500,
                      "modo": "privacidad",
                      "privacidad": "contacts"
                    },
                    "fondo": "#25D366",
                    "texto": "Hoy abrimos hasta las 20:00",
                    "tipo": "text"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoEstado"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "created_at": "2026-10-24T15:08:12Z",
                  "generation": 1,
                  "idempotency_key": "crm-envio-0001",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "status": "en_cola",
                  "type": "message.status_text",
                  "updated_at": "2026-10-24T15:08:12Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/Comando"
                }
              }
            },
            "description": "Accepted",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope status:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Publicar un status (P030)",
        "tags": [
          "Status"
        ]
      }
    },
    "/v1/instances/{id}/status/audience": {
      "get": {
        "description": "Scope `status:read`. Pregunta a WhatsApp la privacidad de status del número y cuenta su audiencia, sin publicar nada: es lo que hay que declarar al publicar en `modo: privacidad`. 409 `no_conectada` sin conexión.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "audiencia-status",
        "parameters": [
          {
            "description": "ID de la instancia.",
            "example": "8a1d2c3e-0000-4000-8000-0000000000a1",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la instancia.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "destinatarios": 1,
                  "horas_retencion": 1,
                  "max_destinatarios_ajustes": 1,
                  "privacidad": "contacts"
                },
                "schema": {
                  "$ref": "#/components/schemas/AudienciaEstadoOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope status:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "La audiencia de status del número",
        "tags": [
          "Status"
        ]
      }
    },
    "/v1/media/{id}": {
      "delete": {
        "description": "Scope `media:write`. Quita el archivo del bucket (o cancela la descarga o importación pendiente) y deja el medio `borrado`. Si un envío pendiente lo usa, 409 `en_uso`. Repetirlo no hace nada.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "borrar-medio",
        "parameters": [
          {
            "description": "ID del medio (media_id).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID del medio (media_id).",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "bytes": 48213,
                  "created_at": "2026-10-24T15:08:12Z",
                  "estado": "pendiente",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                  "metadatos": {},
                  "origen": "subida"
                },
                "schema": {
                  "$ref": "#/components/schemas/Medio"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope media:write.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Borrar un medio o cancelar su descarga",
        "tags": [
          "Multimedia"
        ]
      },
      "get": {
        "description": "Scope `media:read`. El estado (`pendiente` mientras se descarga o importa, `listo`, `fallido` con su `motivo`, `borrado`), el MIME real, el tamaño, el SHA-256, el progreso del trabajo y, si está listo, un permiso temporal de descarga (`descarga.url`, vence en `multimedia.minutos_permiso`). Un medio de otra app es 404.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "obtener-medio",
        "parameters": [
          {
            "description": "ID del medio (media_id).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID del medio (media_id).",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "bytes": 48213,
                  "created_at": "2026-10-24T15:08:12Z",
                  "estado": "pendiente",
                  "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                  "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                  "metadatos": {},
                  "origen": "subida"
                },
                "schema": {
                  "$ref": "#/components/schemas/Medio"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope media:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Ver un medio",
        "tags": [
          "Multimedia"
        ]
      }
    },
    "/v1/media/{id}/content": {
      "get": {
        "description": "Con la API key (scope `media:read`) o con el permiso temporal de `GET /v1/media/{id}` (`?permiso=…`, sin API key). Entrega el archivo en streaming. Con `encoding=base64`, un JSON con el archivo en base64 (P017): solo una salida temporal y acotada por `multimedia.base64_maximo_kb` (más grande: 422 `demasiado_grande_para_base64`); el motor nunca guarda base64. Un medio de otra app es 404; uno que ya no está, 410.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `410`: ya no está disponible.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.\n- `503`: el motor o el transporte de WhatsApp no están disponibles ahora; reintenta más tarde.",
        "operationId": "contenido-medio",
        "parameters": [
          {
            "description": "ID del medio (media_id).",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID del medio (media_id).",
              "type": "string"
            }
          },
          {
            "explode": false,
            "in": "query",
            "name": "encoding",
            "schema": {
              "default": "binario",
              "enum": [
                "binario",
                "base64"
              ],
              "type": "string"
            }
          },
          {
            "description": "Permiso temporal (de GET /v1/media/{id}).",
            "explode": false,
            "in": "query",
            "name": "permiso",
            "schema": {
              "description": "Permiso temporal (de GET /v1/media/{id}).",
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {},
                "schema": {
                  "properties": {
                    "bytes": {
                      "type": "integer"
                    },
                    "data": {
                      "description": "El archivo en base64.",
                      "type": "string"
                    },
                    "encoding": {
                      "enum": [
                        "base64"
                      ],
                      "type": "string"
                    },
                    "media_id": {
                      "format": "uuid",
                      "type": "string"
                    },
                    "mime": {
                      "type": "string"
                    },
                    "sha256": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "contentMediaType": "application/octet-stream",
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "El archivo (binario) o, con `encoding=base64`, un JSON con `data` en base64."
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope media:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "410": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Gone"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "permisoMedia": []
          }
        ],
        "summary": "Descargar un medio",
        "tags": [
          "Multimedia"
        ]
      }
    },
    "/v1/proxies": {
      "get": {
        "description": "Scope `instances:read`. Los crea un operador en la administración (con su credencial sellada y el host en la allowlist); una app solo elige uno para cada instancia.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.",
        "operationId": "v1-listar-proxies",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "elementos": [
                    {
                      "actualizado_en": "2026-10-24T15:08:12Z",
                      "con_credencial": false,
                      "creado_en": "2026-10-24T15:08:12Z",
                      "esquema": "http",
                      "estado": "sin_probar",
                      "host": "texto",
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "instancias": 1,
                      "nombre": "Ventas Centro",
                      "probado_en": "2026-10-24T15:08:12Z",
                      "puerto": 1,
                      "ultimo_error": "texto"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ProxiesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope instances:read.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Los proxies de transporte disponibles",
        "tags": [
          "Instancias"
        ]
      }
    },
    "/v1/subscriptions": {
      "get": {
        "description": "Scope `subscriptions:manage`. Nunca devuelve secretos: solo sus `key_id`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.",
        "operationId": "listar-suscripciones",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "elementos": [
                    {
                      "actualizada_en": "2026-10-24T15:08:12Z",
                      "claves": [
                        {
                          "creado_en": "2026-10-24T15:08:12Z",
                          "key_id": "KEY_ID",
                          "vence_en": "2026-10-24T15:08:12Z"
                        }
                      ],
                      "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                      "creada_en": "2026-10-24T15:08:12Z",
                      "estado": "activa",
                      "fallidas": 1,
                      "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                      "instancias": [
                        "texto"
                      ],
                      "nombre": "Ventas Centro",
                      "ordenado": false,
                      "pendientes": 1,
                      "tipos": [
                        "message.received"
                      ],
                      "url": "https://archivos.ejemplo.com/recurso",
                      "version": 1
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ListaSuscripcionesOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Listar las suscripciones",
        "tags": [
          "Webhooks"
        ]
      },
      "post": {
        "description": "Scope `subscriptions:manage`. La URL tiene que estar en la lista de destinos permitidos de la app (o en la global); los metadatos de la nube se bloquean siempre y no se siguen redirects. Devuelve el **secreto HMAC una sola vez** (`secreto.valor`, con su `key_id`): guárdalo sellado. Cada entrega va firmada: `X-MW-Signature: v1=<hex>` = HMAC-SHA256(secreto, `X-MW-Timestamp` + \".\" + `X-MW-Delivery-Id` + \".\" + body), con `X-MW-Key-Id`; durante la ventana de una rotación llegan dos firmas (separadas por coma, en el orden de los key_id). Verifica la firma sobre el body ANTES de parsearlo y deduplica por `event_id`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "crear-suscripcion",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "nombre": "CRM producción",
                "tipos": [
                  "message.received",
                  "message.updated",
                  "message.sent",
                  "command.failed"
                ],
                "url": "https://crm.ejemplo.com/webhooks/motor"
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoSuscripcion"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "secreto": {
                    "key_id": "KEY_ID",
                    "valor": "texto"
                  },
                  "suscripcion": {
                    "actualizada_en": "2026-10-24T15:08:12Z",
                    "claves": [
                      {
                        "creado_en": "2026-10-24T15:08:12Z",
                        "key_id": "KEY_ID",
                        "vence_en": "2026-10-24T15:08:12Z"
                      }
                    ],
                    "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                    "creada_en": "2026-10-24T15:08:12Z",
                    "estado": "activa",
                    "fallidas": 1,
                    "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                    "instancias": [
                      "texto"
                    ],
                    "nombre": "Ventas Centro",
                    "ordenado": false,
                    "pendientes": 1,
                    "tipos": [
                      "message.received"
                    ],
                    "url": "https://archivos.ejemplo.com/recurso",
                    "version": 1
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/SuscripcionCreada"
                }
              }
            },
            "description": "Created"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Crear una suscripción de webhooks",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/subscriptions/{id}": {
      "delete": {
        "description": "Scope `subscriptions:manage`. No crea entregas nuevas ni entrega las pendientes; nunca borra eventos del ledger.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "eliminar-suscripcion",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Eliminar una suscripción",
        "tags": [
          "Webhooks"
        ]
      },
      "get": {
        "description": "Una suscripción de webhooks: su URL, sus filtros (instancias y tipos), si entrega en orden, su estado (activa, pausada o suspendida por un 401/403 del destino) y los `key_id` de sus secretos vigentes; nunca el secreto.\n\n**Scope:** `subscriptions:manage`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "ver-suscripcion",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "claves": [
                    {
                      "creado_en": "2026-10-24T15:08:12Z",
                      "key_id": "KEY_ID",
                      "vence_en": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "activa",
                  "fallidas": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "instancias": [
                    "texto"
                  ],
                  "nombre": "Ventas Centro",
                  "ordenado": false,
                  "pendientes": 1,
                  "tipos": [
                    "message.received"
                  ],
                  "url": "https://archivos.ejemplo.com/recurso",
                  "version": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/Vista"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Ver una suscripción",
        "tags": [
          "Webhooks"
        ]
      },
      "patch": {
        "description": "Scope `subscriptions:manage`. `estado: activa` reactiva una suscripción suspendida por un 401/403 y lo pendiente sale ya.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "actualizar-suscripcion",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "pausar": {
                  "summary": "Pausar",
                  "value": {
                    "estado": "pausada"
                  }
                },
                "reactivar": {
                  "summary": "Reactivar",
                  "value": {
                    "estado": "activa"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoPatchSuscripcion"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "actualizada_en": "2026-10-24T15:08:12Z",
                  "claves": [
                    {
                      "creado_en": "2026-10-24T15:08:12Z",
                      "key_id": "KEY_ID",
                      "vence_en": "2026-10-24T15:08:12Z"
                    }
                  ],
                  "cliente_id": "8a1d2c3e-0000-4000-8000-0000e5d0f957",
                  "creada_en": "2026-10-24T15:08:12Z",
                  "estado": "activa",
                  "fallidas": 1,
                  "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                  "instancias": [
                    "texto"
                  ],
                  "nombre": "Ventas Centro",
                  "ordenado": false,
                  "pendientes": 1,
                  "tipos": [
                    "message.received"
                  ],
                  "url": "https://archivos.ejemplo.com/recurso",
                  "version": 1
                },
                "schema": {
                  "$ref": "#/components/schemas/Vista"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Cambiar una suscripción (también pausar o reactivar)",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/subscriptions/{id}/replays": {
      "post": {
        "description": "Scope `deliveries:replay`. Un rango de seq de una instancia (`instancia_id`, `desde_seq`, `hasta_seq`, hasta 10 000) o hasta 500 `event_ids`, con `motivo` e `Idempotency-Key` obligatoria. Crea **entregas nuevas de los mismos hechos** (mismo `event_id` y `occurred_at`) dentro del alcance de la suscripción. **Nunca reenvía nada a WhatsApp.**\n\n**Asíncrona:** no es un comando de WhatsApp: responde `202` y crea entregas nuevas de los mismos eventos (mismo `event_id`), que salen por el webhook de la suscripción; síguelas en `GET /v1/deliveries`.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: la `Idempotency-Key` ya se usó con otro pedido.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "replay-suscripcion",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          },
          {
            "example": "crm-envio-0001",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "eventos": {
                  "summary": "Eventos",
                  "value": {
                    "event_ids": [
                      "e1f0c2d4-0000-4000-8000-000000001187"
                    ],
                    "motivo": "Reprocesar un evento"
                  }
                },
                "rango": {
                  "summary": "Rango",
                  "value": {
                    "desde_seq": 1180,
                    "hasta_seq": 1187,
                    "instancia_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                    "motivo": "El CRM perdió estos eventos en un despliegue"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CuerpoReplay"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "creado_en": "2026-10-24T15:08:12Z",
                  "entregas": 1,
                  "replay_id": "8a1d2c3e-0000-4000-8000-00007358a37a",
                  "suscripcion_id": "8a1d2c3e-0000-4000-8000-0000505170bd"
                },
                "schema": {
                  "$ref": "#/components/schemas/Replay"
                }
              }
            },
            "description": "Accepted"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope deliveries:replay.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Revisa los datos enviados: «extra» no es un campo admitido.",
                  "errors": [
                    {
                      "location": "body.extra",
                      "message": "no es un campo admitido"
                    }
                  ],
                  "status": 422,
                  "title": "Unprocessable Entity"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Reenviar eventos ya aceptados (replay)",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/subscriptions/{id}/rotate": {
      "post": {
        "description": "Scope `subscriptions:manage`. Devuelve el secreto nuevo UNA vez. Durante la ventana de Ajustes (60 min por omisión) cada entrega lleva las dos firmas; después, solo la nueva.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `409`: choca con el estado actual (por ejemplo, la instancia no está conectada: `no_conectada`); `detail` dice por qué.\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "rotar-secreto",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "key_id": "KEY_ID",
                  "valor": "texto"
                },
                "schema": {
                  "$ref": "#/components/schemas/SecretoEmitido"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Conflict"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Rotar el secreto HMAC",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/subscriptions/{id}/test": {
      "post": {
        "description": "Scope `subscriptions:manage`. Manda un evento `webhook.test` firmado (fuera del ledger) y devuelve el status.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).\n- `403`: a tu key le falta el scope o está restringida a otras instancias.\n- `404`: no existe para tu app (nunca se dice si es de otra).\n- `422`: un parámetro o el cuerpo no son válidos (un campo de más también); `detail` y `errors` dicen cuál y por qué.",
        "operationId": "probar-suscripcion",
        "parameters": [
          {
            "description": "ID de la suscripción.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "description": "ID de la suscripción.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "duracion_ms": 1,
                  "ok": false
                },
                "schema": {
                  "$ref": "#/components/schemas/Prueba"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "Tu API key no tiene el scope subscriptions:manage.",
                  "status": 403,
                  "title": "Forbidden"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unprocessable Entity"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Probar el destino",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/v1/whoami": {
      "get": {
        "description": "Devuelve la app cliente y la key con que firmas la request: su prefijo, su entorno, sus scopes y las instancias a las que está restringida (vacío: todas las de la app). Úsalo para comprobar la configuración de tu integración.\n\n**Scope:** ninguno: sirve cualquier key válida.\n\n**Errores típicos:**\n\n- `401`: falta la API key o no es válida, venció o fue revocada (o la app está suspendida).",
        "operationId": "whoami",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "cliente": {
                    "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                    "nombre": "Ventas Centro"
                  },
                  "key": {
                    "entorno": "live",
                    "id": "8a1d2c3e-0000-4000-8000-000037386ae0",
                    "instancias": [
                      "texto"
                    ],
                    "prefijo": "mw_live_PREFIJO",
                    "scopes": [
                      "messages:send",
                      "messages:read",
                      "events:read"
                    ]
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/WhoamiOutputBody"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "La API key no es válida, venció, fue revocada o su app está suspendida.",
                  "status": 401,
                  "title": "Unauthorized"
                },
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Unauthorized"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "summary": "Qué app y qué key hacen la request",
        "tags": [
          "Apps cliente"
        ]
      }
    }
  },
  "webhooks": {
    "appstate.changed": {
      "post": {
        "description": "Un cambio del appstate de un chat: fijar, archivar, silenciar, marcar leído o no leído, destacar un mensaje, borrar el chat o el candado (accion), con el estado del chat después del cambio. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-appstate-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "accion": "fijar",
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "coleccion": "regular",
                  "desde": "whatsapp",
                  "full_sync": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "appstate.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoAppstateChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "appstate.changed: Cambió el estado de un chat en WhatsApp.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "appstate.sync": {
      "post": {
        "description": "Una colección del appstate quedó al día, con error o esperando una clave que falta. error trae un código acotado; recuperacion dice si fue la copia que mandó el teléfono a pedido del motor.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-appstate-sync",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "coleccion": "regular",
                  "estado": "al_dia",
                  "full_sync": false,
                  "recuperacion": false,
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "appstate.sync"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoAppstateSync"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "appstate.sync: Cambió la sincronización de una colección del appstate.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "blocklist.changed": {
      "post": {
        "description": "Se bloquearon o desbloquearon contactos; cambios trae cada uno con su estado nuevo. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Perfil y privacidad. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-blocklist-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "cambios": [
                    {
                      "bloqueado": false,
                      "cambio_en": "2026-10-24T15:08:12Z",
                      "contacto": {
                        "aliases": [
                          "CONTACTO@lid"
                        ],
                        "clase": "usuario",
                        "jid": "CONTACTO@s.whatsapp.net",
                        "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                      },
                      "desde": "texto"
                    }
                  ],
                  "desde": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "blocklist.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoBlocklistChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "blocklist.changed: Cambió la lista de bloqueados.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.accept": {
      "post": {
        "description": "La llamada se aceptó (en el teléfono u otro dispositivo).\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-accept",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.accept"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallAccept"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.accept: La llamada se aceptó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.offer": {
      "post": {
        "description": "Una llamada entrante (de voz o de video). elementos trae, como diagnóstico, los nombres de los elementos de la oferta.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-offer",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.offer"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallOffer"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.offer: Entra una llamada.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.offer_notice": {
      "post": {
        "description": "El aviso de una oferta de llamada (por ejemplo, de una llamada de grupo) que WhatsApp manda en lugar de la oferta completa.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-offer-notice",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.offer_notice"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallOfferNotice"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.offer_notice: Aviso de una llamada entrante.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.preaccept": {
      "post": {
        "description": "Una señal de preaceptación de la llamada que informa WhatsApp.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-preaccept",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.preaccept"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallPreaccept"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.preaccept: La llamada se preaceptó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.reject": {
      "post": {
        "description": "Una señal de rechazo que llegó de WhatsApp (por ejemplo, la rechazaron en el teléfono). El rechazo que hace el motor es call.rejected.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-reject",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.reject"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallReject"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.reject: WhatsApp informó el rechazo de la llamada.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.rejected": {
      "post": {
        "description": "El motor rechazó la llamada: solo (rechazo automatico, por la configuración de la instancia) o a pedido (operador o app). El sobre trae el command_id del rechazo.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-rejected",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.rejected"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallRejected"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.rejected: El motor rechazó una llamada.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.signal": {
      "post": {
        "description": "Cualquier otra señal de una llamada que el motor no clasifica aparte.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-signal",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.signal"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallSignal"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.signal: Otra señal de llamada.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "call.terminate": {
      "post": {
        "description": "La llamada terminó; motivo trae el código que informa WhatsApp.\n\nGrupo: Llamadas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-call-terminate",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "call_id": "CALL_ID",
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "video": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "call.terminate"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCallTerminate"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "call.terminate: La llamada terminó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "chat.ephemeral": {
      "post": {
        "description": "Alguien activó, cambió o desactivó (segundos 0) los mensajes temporales de un chat. Si lo hizo un comando del motor, el sobre trae su command_id.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-chat-ephemeral",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "segundos": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "chat.ephemeral"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoChatEphemeral"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "chat.ephemeral: Cambió el temporizador de mensajes temporales de un chat.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "chat.note": {
      "post": {
        "description": "Se creó, se editó o se eliminó la nota de un chat en WhatsApp Business. El motor no escribe notas: siempre llega desde whatsapp.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-chat-note",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "coleccion": "regular",
                  "desde": "whatsapp",
                  "full_sync": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "nota": {
                    "eliminada": false,
                    "nota_id": "8a1d2c3e-0000-4000-8000-0000456d4c67",
                    "tipo": "no_estructurada"
                  },
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "chat.note"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoChatNote"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "chat.note: Cambió la nota de un chat de WhatsApp Business.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "command.accepted": {
      "post": {
        "description": "El comando quedó guardado y en cola para ejecutarse. El sobre trae command_id (y correlation_id, si lo mandaste). respaldo_de aparece en el texto de respaldo que el motor manda después de una lista.\n\nGrupo: Comandos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-command-accepted",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "type": "message.text"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "command.accepted"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCommandAccepted"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "command.accepted: Un comando quedó aceptado.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "command.ambiguous": {
      "post": {
        "description": "El comando quedó en la frontera: pudo haber llegado a WhatsApp y no hubo confirmación. El motor nunca lo reintenta; si después llega un eco o un receipt, lo concilia y emite message.sent con conciliado. El sobre trae command_id.\n\nGrupo: Comandos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-command-ambiguous",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "error_code": "resultado_incierto",
                  "stage": "frontera",
                  "type": "message.text"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "command.ambiguous"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCommandAmbiguous"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "command.ambiguous: No se sabe si el comando tuvo efecto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "command.cancelled": {
      "post": {
        "description": "El comando se canceló antes de ejecutarse. El sobre trae command_id.\n\nGrupo: Comandos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-command-cancelled",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "type": "message.received"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "command.cancelled"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCommandCancelled"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "command.cancelled: Un comando se canceló.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "command.failed": {
      "post": {
        "description": "El comando terminó sin efecto: no salió, WhatsApp lo rechazó o falló una validación al ejecutarlo. El sobre trae command_id. Un envío trae stage y provider_message_id; server_code y server_origin aparecen si WhatsApp respondió con un código.\n\nGrupo: Comandos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-command-failed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "error_code": "destino_invalido",
                  "stage": "previa",
                  "type": "message.text"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "command.failed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCommandFailed"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "command.failed: Un comando falló.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "community.changed": {
      "post": {
        "description": "Cambió el vínculo entre una comunidad y uno de sus grupos. Si un grupo pasa a otra comunidad, llega uno con vinculado false y motivo otra_comunidad por la anterior. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Grupos y comunidades. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-community-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "comunidad": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "grupo": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "version": 1,
                  "vinculado": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "community.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoCommunityChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "community.changed: Un grupo entró a una comunidad o salió de ella.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "connected": {
      "post": {
        "description": "La sesión quedó conectada y autenticada con WhatsApp. El data solo trae la generación; el estado nuevo llega en state.changed.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-connected",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "connected"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoConnected"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "connected: La sesión se conectó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "contact.about": {
      "post": {
        "description": "Cambió la «info» de un contacto, si la comparte (por un aviso de WhatsApp o una consulta de perfil).\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-contact-about",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "libreta",
                  "contacto": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "contacto": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "creado_en": "2026-10-24T15:08:12Z",
                    "en_libreta": false
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "origen": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "contact.about"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoContactAbout"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "contact.about: Cambió el recado (about) de un contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "contact.business_name": {
      "post": {
        "description": "Cambió el nombre verificado de una cuenta de WhatsApp Business.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-contact-business-name",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "libreta",
                  "contacto": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "contacto": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "creado_en": "2026-10-24T15:08:12Z",
                    "en_libreta": false
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "origen": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "contact.business_name"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoContactBusinessName"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "contact.business_name: Cambió el nombre de negocio de un contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "contact.picture": {
      "post": {
        "description": "Cambió (o se quitó) la foto de perfil de un contacto; trae su ID, la imagen se consulta aparte.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-contact-picture",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "libreta",
                  "contacto": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "contacto": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "creado_en": "2026-10-24T15:08:12Z",
                    "en_libreta": false
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "origen": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "contact.picture"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoContactPicture"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "contact.picture: Cambió la foto de perfil de un contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "contact.push_name": {
      "post": {
        "description": "Cambió el push_name de un contacto (el nombre que él eligió).\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-contact-push-name",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "libreta",
                  "contacto": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "contacto": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "creado_en": "2026-10-24T15:08:12Z",
                    "en_libreta": false
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "origen": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "contact.push_name"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoContactPushName"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "contact.push_name: Cambió el nombre que manda un contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "contact.updated": {
      "post": {
        "description": "Un contacto se guardó, se renombró o se borró de la libreta del teléfono (accion). La libreta inicial de una sincronización completa no deja eventos.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-contact-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "libreta",
                  "contacto": {
                    "actualizado_en": "2026-10-24T15:08:12Z",
                    "contacto": {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    },
                    "creado_en": "2026-10-24T15:08:12Z",
                    "en_libreta": false
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "origen": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "contact.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoContactUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "contact.updated: Cambió un contacto en la libreta del teléfono.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "disconnected": {
      "post": {
        "description": "El socket se cerró con la sesión todavía vinculada: por una caída (el SDK reconecta solo), un reinicio del motor o a pedido (desconectar o pausar). El motivo dice cuál.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-disconnected",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "motivo": "pedido del cliente"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "disconnected"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoDisconnected"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "disconnected: La sesión se desconectó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "error": {
      "post": {
        "description": "Un error tipificado de la conexión: la reconexión del SDK se agotó, WhatsApp rechazó la conexión, la versión quedó desactualizada, un error de stream o el dispositivo ya no está. permanente dice si el motor lo reintenta solo.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-error",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "motivo": "sin_conexion",
                  "permanente": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "error"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoError"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "error: Un error de conexión o de sesión.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "group.changed": {
      "post": {
        "description": "Uno o más atributos del grupo cambiaron (nombre, descripción, ajustes, foto, comunidad, el rol o la membresía del número…); campos trae solo lo que cambió. Si el cambio salió de un comando, el sobre trae su command_id.\n\nGrupo: Grupos y comunidades. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-group-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campos": {},
                  "desde": "whatsapp",
                  "grupo": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  }
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "group.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoGroupChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "group.changed: Cambió la información o los ajustes de un grupo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "group.joined": {
      "post": {
        "description": "El número entró a un grupo: lo creó (tipo new), lo agregaron o entró por una invitación. Si lo hizo un comando (crear o unirse), el sobre trae su command_id.\n\nGrupo: Grupos y comunidades. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-group-joined",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "desde": "whatsapp",
                  "es_comunidad": false,
                  "grupo": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "motivo": "pedido del cliente",
                  "nombre": "Ventas Centro",
                  "participantes": 1,
                  "tipo": "message.received"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "group.joined"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoGroupJoined"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "group.joined: El número entró a un grupo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "group.participants": {
      "post": {
        "description": "Entraron, salieron, subieron a administrador o bajaron participantes. Las cuatro listas siempre están (null si no hay nadie en esa lista). Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Grupos y comunidades. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-group-participants",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "degradados": [
                    {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    }
                  ],
                  "desde": "whatsapp",
                  "entran": [
                    {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    }
                  ],
                  "grupo": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "promovidos": [
                    {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    }
                  ],
                  "salen": [
                    {
                      "aliases": [
                        "CONTACTO@lid"
                      ],
                      "clase": "usuario",
                      "jid": "CONTACTO@s.whatsapp.net",
                      "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                    }
                  ]
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "group.participants"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoGroupParticipants"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "group.participants: Cambiaron los participantes de un grupo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "history.sync": {
      "post": {
        "description": "El teléfono mandó un lote de historial (al vincular o a pedido). Trae sus metadatos; los mensajes que se importan llegan aparte como message.received con origin history.\n\nGrupo: Historial. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-history-sync",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "contenido_importado": false,
                  "conversaciones": 1,
                  "fragmento": 1,
                  "generacion": 1,
                  "mensajes": 1,
                  "progreso": 1,
                  "tipo_sync": "texto"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "history.sync"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoHistorySync"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "history.sync: Llegó un lote de historial del teléfono.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "instance.updated": {
      "post": {
        "description": "Alguien cambió el nombre o la configuración de la instancia (PATCH). Trae solo los nombres de los campos que cambiaron, nunca sus valores.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-instance-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campos": [
                    "nombre"
                  ],
                  "generacion": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "instance.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoInstanceUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "instance.updated: Cambió el nombre o la configuración de la instancia.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "interactive.response": {
      "post": {
        "description": "Un clic en un botón, una fila de una lista, un native flow o el número de una opción del respaldo de texto. correlacion dice si se pudo atar a un interactivo de esta instancia; si se correlacionó, el sobre trae el command_id del envío.\n\nGrupo: Interactivos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-interactive-response",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "accion": {},
                  "autor": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "correlacion": "correlacionada",
                  "formato": "buttons_response",
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "interactive.response"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoInteractiveResponse"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "interactive.response: Alguien respondió a un mensaje interactivo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "interactive.response.updated": {
      "post": {
        "description": "Al comprobar un alias (PN y LID), una respuesta que había quedado otro_chat u otro_autor se volvió a correlacionar. Trae la respuesta entera con su correlación nueva y las identidades del hecho original (response_id, response_event_id); no es otra respuesta.\n\nGrupo: Interactivos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-interactive-response-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "accion": {},
                  "autor": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "correlacion": "correlacionada",
                  "correlacion_anterior": "otro_chat",
                  "formato": "buttons_response",
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "response_event_id": "8a1d2c3e-0000-4000-8000-0000dd7e3f97",
                  "response_id": "8a1d2c3e-0000-4000-8000-00007baab4de"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "interactive.response.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoInteractiveResponseUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "interactive.response.updated: Cambió la correlación de una respuesta ya publicada.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "interactive.unknown": {
      "post": {
        "description": "Una respuesta con un formato que el motor no reconoce o con datos inválidos. motivo dice por qué y crudo trae lo que llegó, saneado y acotado.\n\nGrupo: Interactivos. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-interactive-unknown",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "accion": {},
                  "autor": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "correlacion": "correlacionada",
                  "formato": "buttons_response",
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "interactive.unknown"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoInteractiveUnknown"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "interactive.unknown: Llegó una respuesta interactiva que no se pudo leer.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "label.associated": {
      "post": {
        "description": "Una etiqueta quedó puesta en un chat (o en un mensaje, con mensaje). Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-label-associated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "full_sync": false,
                  "label_id": "3",
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "label.associated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLabelAssociated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "label.associated: Se puso una etiqueta en un chat o un mensaje.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "label.created": {
      "post": {
        "description": "Apareció una etiqueta nueva. Si la creó un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-label-created",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "coleccion": "texto",
                  "desde": "whatsapp",
                  "etiqueta": {
                    "actualizada_en": "2026-10-24T15:08:12Z",
                    "chats": 1,
                    "color": 1,
                    "eliminada": false,
                    "label_id": "3",
                    "mensajes": 1,
                    "nombre": "Ventas Centro"
                  },
                  "full_sync": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "label.created"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLabelCreated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "label.created: Se creó una etiqueta de WhatsApp Business.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "label.deleted": {
      "post": {
        "description": "Se eliminó una etiqueta. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-label-deleted",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "coleccion": "texto",
                  "desde": "whatsapp",
                  "etiqueta": {
                    "actualizada_en": "2026-10-24T15:08:12Z",
                    "chats": 1,
                    "color": 1,
                    "eliminada": false,
                    "label_id": "3",
                    "mensajes": 1,
                    "nombre": "Ventas Centro"
                  },
                  "full_sync": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "label.deleted"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLabelDeleted"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "label.deleted: Se eliminó una etiqueta.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "label.dissociated": {
      "post": {
        "description": "Una etiqueta se quitó de un chat (o de un mensaje). Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-label-dissociated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "full_sync": false,
                  "label_id": "3",
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "label.dissociated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLabelDissociated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "label.dissociated: Se quitó una etiqueta de un chat o un mensaje.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "label.updated": {
      "post": {
        "description": "Cambió el nombre o el color de una etiqueta; anterior trae los de antes. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Etiquetas y sincronización. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-label-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "coleccion": "texto",
                  "desde": "whatsapp",
                  "etiqueta": {
                    "actualizada_en": "2026-10-24T15:08:12Z",
                    "chats": 1,
                    "color": 1,
                    "eliminada": false,
                    "label_id": "3",
                    "mensajes": 1,
                    "nombre": "Ventas Centro"
                  },
                  "full_sync": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "version": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "label.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLabelUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "label.updated: Se editó una etiqueta.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "logged_out": {
      "post": {
        "description": "WhatsApp cerró la sesión (origen telefono: la desvincularon desde el teléfono) o se desvinculó a pedido (origen operador). Para volver a usar la instancia hace falta un emparejamiento nuevo.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-logged-out",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "origen": "telefono"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "logged_out"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoLoggedOut"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "logged_out: La sesión se cerró y el vínculo ya no sirve.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "media.failed": {
      "post": {
        "description": "La descarga, la importación o la conversión de un archivo falló de forma permanente; motivo dice por qué (vencido_en_whatsapp, invalido, demasiado_grande…). Si lo usa un envío, el sobre trae su command_id.\n\nGrupo: Multimedia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-media-failed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "estado": "listo",
                  "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                  "origen": "entrante"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "media.failed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMediaFailed"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "media.failed: No se pudo obtener un medio.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "media.ready": {
      "post": {
        "description": "El motor terminó de descargar (o de importar de una URL, o de convertir) un archivo y su copia privada está disponible en GET /v1/media/{id}. Si lo usa un envío, el sobre trae su command_id.\n\nGrupo: Multimedia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-media-ready",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "estado": "listo",
                  "media_id": "8a1d2c3e-0000-4000-8000-0000000000d1",
                  "origen": "entrante"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "media.ready"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMediaReady"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "media.ready: Un medio quedó listo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.expired": {
      "post": {
        "description": "WhatsApp no avisa cuando un mensaje temporal vence: el motor lo vence por su cuenta, borra su contenido y sus medios, y emite este evento una vez. Sus eventos anteriores quedan redactados.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-expired",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "from_me": false,
                  "message_ref": "8a1d2c3e-0000-4000-8000-0000992ae626",
                  "momento": "2026-10-24T15:08:12Z",
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.expired"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageExpired"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.expired: Venció un mensaje temporal.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.reaction": {
      "post": {
        "description": "Una reacción nueva o cambiada sobre objetivo; reaccion vacía significa que la quitó. La última version es la vigente.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-reaction",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "objetivo": {
                    "de_mi": true,
                    "provider_id": "PROVIDER_MESSAGE_ID"
                  },
                  "operacion": "reaccion",
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "reaccion": "👍"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.reaction"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageReaction"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.reaction: Alguien reaccionó a un mensaje.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.received": {
      "post": {
        "description": "Un mensaje nuevo de un chat, de un grupo o de un canal, también uno propio mandado desde otro dispositivo (from_me) y los del historial importado (origin history). Si trae un medio, su descarga sigue con media.ready o media.failed. Si es temporal y vence, el contenido se redacta: llega sin contenido, con redactado y motivo vencido.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-received",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "contenido": {
                    "texto": "Hola, ¿tienen envío a domicilio?",
                    "tipo": "texto"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "nombre_perfil": "Nombre del contacto",
                  "operacion": "mensaje",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.received"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageReceived"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.received: Llegó un mensaje (o el eco de uno propio).",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.revoked": {
      "post": {
        "description": "Alguien borró un mensaje para todos. objetivo dice cuál y version cuántos borrados del mismo mensaje llegaron; no trae contenido.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-revoked",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "operacion": "mensaje",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.revoked"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageRevoked"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.revoked: Un mensaje se borró para todos.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.sent": {
      "post": {
        "description": "El servidor de WhatsApp aceptó un mensaje, una edición, un borrado o una reacción que mandó el motor; no significa entregado ni leído. El sobre trae command_id. Con conciliado, el comando había quedado ambiguo y lo confirmó un eco o un receipt.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-sent",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "aceptado_en": "2026-10-24T15:08:12Z",
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "command_id": "8a1d2c3e-0000-4000-8000-00008079be9a",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.sent"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageSent"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.sent: WhatsApp aceptó un envío del motor.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.undecryptable": {
      "post": {
        "description": "Un mensaje llegó y no se pudo leer; nunca trae texto. Si después llega legible (el remitente o el teléfono lo reenvían), llega como message.received con el mismo provider_id.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-undecryptable",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "no_disponible": false,
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.undecryptable"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageUndecryptable"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.undecryptable: Llegó un mensaje que no se pudo descifrar.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "message.updated": {
      "post": {
        "description": "operacion dice qué cambió: edicion (con su contenido nuevo y version), estado (subió a entregado, leido o reproducido; estado y anterior) o ubicacion_actualizada. Puede traer command_id cuando el cambio sale de un comando. La edición de un mensaje temporal se redacta con él.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-message-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "anterior": "entregado",
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "estado": "leido",
                  "from_me": true,
                  "momento": "2026-10-24T15:08:12Z",
                  "operacion": "estado",
                  "provider_id": "PROVIDER_MESSAGE_ID"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "message.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoMessageUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "message.updated: Un mensaje cambió: edición, estado o ubicación en vivo.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "newsletter.changed": {
      "post": {
        "description": "Uno o más datos del canal cambiaron (nombre, descripción, estado, verificado, rol, seguimiento o silencio); campos trae solo lo que cambió.\n\nGrupo: Canales. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-newsletter-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campos": {},
                  "canal": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "newsletter.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoNewsletterChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "newsletter.changed: Cambió la información de un canal.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "newsletter.joined": {
      "post": {
        "description": "El número sigue (o creó) un canal. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Canales. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-newsletter-joined",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "canal": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "nombre": "Ventas Centro",
                  "rol": "owner"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "newsletter.joined"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoNewsletterJoined"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "newsletter.joined: El número empezó a seguir un canal.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "newsletter.left": {
      "post": {
        "description": "El número dejó un canal (también si una consulta muestra que ya no lo sigue). Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Canales. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-newsletter-left",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "canal": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "rol": "texto"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "newsletter.left"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoNewsletterLeft"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "newsletter.left: El número dejó de seguir un canal.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "newsletter.muted": {
      "post": {
        "description": "Cambió el silencio de un canal que sigue el número. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Canales. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-newsletter-muted",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "canal": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "silenciado": false
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "newsletter.muted"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoNewsletterMuted"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "newsletter.muted: Se silenció o se reactivó un canal.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "newsletter.updates": {
      "post": {
        "description": "Un aviso (en vivo o de una consulta) cambió las vistas o las reacciones de una o más publicaciones de un canal. Solo trae las publicaciones que cambiaron.\n\nGrupo: Canales. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-newsletter-updates",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "canal": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "desde": "whatsapp",
                  "publicaciones": [
                    {
                      "reacciones": {},
                      "server_id": 125,
                      "vistas": 1
                    }
                  ]
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "newsletter.updates"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoNewsletterUpdates"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "newsletter.updates: Cambiaron las vistas o las reacciones de publicaciones.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "paired": {
      "post": {
        "description": "WhatsApp aceptó el vínculo y el dispositivo quedó guardado; la sesión todavía no está autenticada (falta connected). Con conciliado, el vínculo se confirmó al arrancar el motor.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-paired",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "paired"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPaired"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "paired: El teléfono se vinculó.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "pairing.available": {
      "post": {
        "description": "Llega con el primer QR o código de un intento de emparejamiento (los QR siguientes del mismo intento no repiten el evento). El valor del reto no viaja: léelo del emparejamiento de la instancia antes de expira_en.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-pairing-available",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "expira_en": "2026-10-24T15:08:12Z",
                  "generacion": 1,
                  "modo": "qr",
                  "reto": "qr"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "pairing.available"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPairingAvailable"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "pairing.available: Hay un reto de emparejamiento para mostrar.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "pairing.expired": {
      "post": {
        "description": "Se acabaron los QR del intento o venció el código sin que se vinculara el teléfono. No es un cierre de sesión: puedes pedir otro emparejamiento.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-pairing-expired",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "motivo": "qr_vencido"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "pairing.expired"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPairingExpired"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "pairing.expired: Venció el intento de emparejamiento.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "pairing.failed": {
      "post": {
        "description": "El intento terminó con un error (el teléfono rechazado, una versión desactualizada, una conexión que no se pudo abrir…). El motivo es un código acotado.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-pairing-failed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "motivo": "pedido del cliente"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "pairing.failed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPairingFailed"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "pairing.failed: El intento de emparejamiento falló.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "peer.merged": {
      "post": {
        "description": "El motor había visto un contacto por separado (por ejemplo, por su número y por su LID) y el servidor confirmó que es el mismo: los peer_ref de unidos dejan de existir y todo lo suyo pasa a peer. Si guardas conversaciones por peer_ref, júntalas. Un envío a un peer_ref unido responde 422.\n\nGrupo: Contactos y chats. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-peer-merged",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "peer": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "unidos": [
                    "texto"
                  ]
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "peer.merged"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPeerMerged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "peer.merged: Dos peers resultaron el mismo contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "poll.vote": {
      "post": {
        "description": "Un voto (o su cambio) en una encuesta; reemplaza el voto anterior del mismo votante. Trae el resultado agregado; si no se pudo descifrar, descifrado es false y nunca se inventa una opción.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-poll-vote",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "descifrado": false,
                  "encuesta": "texto",
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "opciones": [
                    "texto"
                  ],
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "resultado": {
                    "conocida": false,
                    "opciones": [
                      {
                        "opcion": "texto",
                        "votos": 1
                      }
                    ],
                    "provider_id": "PROVIDER_MESSAGE_ID",
                    "seleccionables": 1,
                    "sin_descifrar": 1,
                    "votantes": 1
                  },
                  "vigente": false,
                  "votante": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  }
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "poll.vote"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPollVote"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "poll.vote: Alguien votó en una encuesta.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "presence": {
      "post": {
        "description": "Solo llega para los contactos con una suscripción de presencia vigente: si está disponible, su última vez (si la comparte) o si escribe o graba en un chat. La presencia de los demás no va al ledger.\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-presence",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "de": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "momento": "2026-10-24T15:08:12Z",
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "presence"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPresence"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "presence: Cambió la presencia de un contacto suscrito.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "privacy.changed": {
      "post": {
        "description": "Cambió una o más opciones de privacidad (cambiadas) o el temporizador por defecto (temporizador_por_defecto). privacidad trae todas las opciones conocidas. Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Perfil y privacidad. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-privacy-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "cambiadas": [
                    "texto"
                  ],
                  "desde": "whatsapp",
                  "privacidad": {}
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "privacy.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoPrivacyChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "privacy.changed: Cambió la privacidad del número.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "profile.updated": {
      "post": {
        "description": "Cambió el nombre, el recado o la foto del número (desde el teléfono, un comando o lo que mostró una consulta). Si lo hizo un comando, el sobre trae su command_id.\n\nGrupo: Perfil y privacidad. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-profile-updated",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "campo": "nombre",
                  "desde": "whatsapp",
                  "momento": "2026-10-24T15:08:12Z"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "profile.updated"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoProfileUpdated"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "profile.updated: Cambió el perfil propio del número.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "provider.unknown": {
      "post": {
        "description": "Un hecho durable del SDK que el motor todavía no modela queda en el ledger tal cual, con su tipo en sdk_tipo, para no confirmar nada sin guardarlo. Su forma puede cambiar con la versión del SDK: no construyas lógica sobre sdk.\n\n**Esquema parcial:** sdk es el evento del SDK serializado: su forma depende de sdk_tipo y de la versión fijada de whatsmeow.\n\nGrupo: Otros. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-provider-unknown",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1,
                  "sdk_tipo": "texto"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "provider.unknown"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoProviderUnknown"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "provider.unknown: Un evento del proveedor que el motor no clasifica.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "query.completed": {
      "post": {
        "description": "Una consulta del catálogo o de las colecciones de un negocio terminó bien. No trae el resultado: se lee con su consulta_id mientras su cursor sigue vigente (vence_en).\n\nGrupo: Consultas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-query-completed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "cantidad": 1,
                  "consulta_id": "8a1d2c3e-0000-4000-8000-0000242516f2",
                  "operacion": "catalogo",
                  "resultado": "ok",
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "query.completed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoQueryCompleted"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "query.completed: Terminó una consulta comercial.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "query.failed": {
      "post": {
        "description": "Una consulta del catálogo o de las colecciones de un negocio falló; trae solo la operación y el código, nunca datos del negocio.\n\nGrupo: Consultas. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-query-failed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "codigo": "texto",
                  "consulta_id": "8a1d2c3e-0000-4000-8000-0000242516f2",
                  "operacion": "catalogo"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "query.failed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoQueryFailed"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "query.failed: Falló una consulta comercial.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "receipt": {
      "post": {
        "description": "Un acuse de entrega, lectura o reproducción (también los propios desde otro dispositivo). aplicados cuenta los mensajes conocidos que subieron de estado; pendientes, los que todavía no llegaron y se aplican cuando lleguen. tipo: entregado, leido, reproducido, leido_propio, reproducido_propio, remitente, reintento u otro (con tipo_proveedor).\n\nGrupo: Mensajes. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-receipt",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "aplicados": 1,
                  "chat": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "es_grupo": false,
                  "from_me": false,
                  "momento": "2026-10-24T15:08:12Z",
                  "pendientes": 1,
                  "provider_ids": [
                    "PROVIDER_MESSAGE_ID"
                  ],
                  "tipo": "message.received"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "receipt"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoReceipt"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "receipt: Llegó un receipt de uno o más mensajes.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "state.changed": {
      "post": {
        "description": "Llega cada vez que la instancia pasa de un estado a otro (de, a y el motivo tipificado), incluida su creación (de en null). No trae command_id: el comando que lo provocó deja su propio command.*.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-state-changed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "a": "conectado",
                  "de": "emparejando",
                  "generacion": 1,
                  "motivo": ""
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "state.changed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoStateChanged"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "state.changed: Cambió el estado observado de la instancia.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "status.received": {
      "post": {
        "description": "Un status nuevo de un contacto (o uno propio publicado desde otro dispositivo); el archivo no se descarga, solo su tipo, su MIME y su texto. El contenido se muestra hasta retener_hasta: después, o si su autor lo borra, el data llega redactado.\n\nGrupo: Status. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-status-received",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "from_me": false,
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "retener_hasta": "2026-10-24T15:08:12Z",
                  "status_id": "8a1d2c3e-0000-4000-8000-0000bbefc4cd",
                  "tipo": "message.received",
                  "vence_en": "2026-10-24T15:08:12Z"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "status.received"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoStatusReceived"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "status.received: Llegó un status (historia) de un contacto.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "status.revoked": {
      "post": {
        "description": "Quien publicó un status lo borró; su status.received queda redactado. Llega una vez por historia.\n\n**Esquema parcial:** autor llega en null cuando from_me es true (el esquema lo publica como objeto).\n\nGrupo: Status. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-status-revoked",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "autor": {
                    "aliases": [
                      "CONTACTO@lid"
                    ],
                    "clase": "usuario",
                    "jid": "CONTACTO@s.whatsapp.net",
                    "peer_ref": "8a1d2c3e-0000-4000-8000-00000477ac4b"
                  },
                  "from_me": false,
                  "provider_id": "PROVIDER_MESSAGE_ID",
                  "status_id": "8a1d2c3e-0000-4000-8000-0000bbefc4cd"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "status.revoked"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoStatusRevoked"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "status.revoked: Se borró un status.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "stream_replaced": {
      "post": {
        "description": "Otra conexión usa las mismas claves: el motor detiene la instancia, abre una alerta y no reconecta solo para no pelear el socket.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-stream-replaced",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "generacion": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "stream_replaced"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoStreamReplaced"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "stream_replaced: Otra conexión tomó la sesión.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "sync.completed": {
      "post": {
        "description": "El trabajo de historial terminó con lo que el teléfono mandó (motivo dice por qué). WhatsApp no garantiza la historia completa. Si lo creó un comando, el sobre trae su command_id.\n\nGrupo: Historial. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-sync-completed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "aviso": "texto",
                  "chat_actual": 1,
                  "chats": 1,
                  "duplicados": 1,
                  "estado": "en_curso",
                  "historia_completa": false,
                  "importados": 1,
                  "lotes_importados": 1,
                  "lotes_recibidos": 1,
                  "mas_nuevo_en": "2026-10-24T15:08:12Z",
                  "mas_viejo_en": "2026-10-24T15:08:12Z",
                  "motivo": "pedido del cliente",
                  "no_soportados": 1,
                  "omitidos_cuota": 1,
                  "omitidos_fecha": 1,
                  "pedidos": 1,
                  "progreso": 1,
                  "sin_respuesta": 1,
                  "sync_job_id": "8a1d2c3e-0000-4000-8000-00006aee4d56",
                  "tipo": "inicial"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "sync.completed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoSyncCompleted"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "sync.completed: Terminó un trabajo de historial.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "sync.failed": {
      "post": {
        "description": "El trabajo de historial se canceló o falló (estado y motivo dicen cuál); lo que quedaba por importar se omite. Si lo creó un comando, el sobre trae su command_id.\n\nGrupo: Historial. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-sync-failed",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "aviso": "texto",
                  "chat_actual": 1,
                  "chats": 1,
                  "duplicados": 1,
                  "estado": "en_curso",
                  "historia_completa": false,
                  "importados": 1,
                  "lotes_importados": 1,
                  "lotes_recibidos": 1,
                  "mas_nuevo_en": "2026-10-24T15:08:12Z",
                  "mas_viejo_en": "2026-10-24T15:08:12Z",
                  "motivo": "pedido del cliente",
                  "no_soportados": 1,
                  "omitidos_cuota": 1,
                  "omitidos_fecha": 1,
                  "pedidos": 1,
                  "progreso": 1,
                  "sin_respuesta": 1,
                  "sync_job_id": "8a1d2c3e-0000-4000-8000-00006aee4d56",
                  "tipo": "inicial"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "sync.failed"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoSyncFailed"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "sync.failed: Un trabajo de historial se canceló o falló.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "sync.progress": {
      "post": {
        "description": "Un trabajo de historial avanzó (importó un lote, mandó un pedido, se pausó…). Si lo creó un comando, el sobre trae su command_id.\n\nGrupo: Historial. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-sync-progress",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "aviso": "texto",
                  "chat_actual": 1,
                  "chats": 1,
                  "duplicados": 1,
                  "estado": "en_curso",
                  "historia_completa": false,
                  "importados": 1,
                  "lotes_importados": 1,
                  "lotes_recibidos": 1,
                  "mas_nuevo_en": "2026-10-24T15:08:12Z",
                  "mas_viejo_en": "2026-10-24T15:08:12Z",
                  "motivo": "pedido del cliente",
                  "no_soportados": 1,
                  "omitidos_cuota": 1,
                  "omitidos_fecha": 1,
                  "pedidos": 1,
                  "progreso": 1,
                  "sin_respuesta": 1,
                  "sync_job_id": "8a1d2c3e-0000-4000-8000-00006aee4d56",
                  "tipo": "inicial"
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "sync.progress"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoSyncProgress"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "sync.progress: Avanzó un trabajo de historial.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "temporary_ban": {
      "post": {
        "description": "WhatsApp informó un bloqueo temporal del número. La instancia queda bloqueada hasta expira_en (si WhatsApp lo dijo) y se abre una alerta crítica.\n\nGrupo: Instancia. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-temporary-ban",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "codigo": 1,
                  "generacion": 1
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "temporary_ban"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoTemporaryBan"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "temporary_ban: WhatsApp bloqueó el número temporalmente.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    },
    "webhook.test": {
      "post": {
        "description": "La manda el botón o el endpoint de prueba de una suscripción, firmada y por el mismo camino que las entregas. No está en el ledger: instance_id es el UUID nulo y seq y generation valen 0.\n\nGrupo: Webhooks. Llega igual por `GET /v1/instances/{id}/events`, por los streams SSE y WebSocket y por los bridges; por webhook, como un `POST` firmado a la URL de tu suscripción (si su filtro de `tipos` lo incluye).",
        "operationId": "evento-webhook-test",
        "parameters": [
          {
            "description": "`v1=<hex>`: HMAC-SHA256 con el secreto de la suscripción sobre `X-MW-Timestamp + \".\" + X-MW-Delivery-Id + \".\" + body` (el body crudo, tal cual llegó). Durante la ventana de una rotación llegan dos firmas separadas por coma, en el orden de `X-MW-Key-Id`. Verifícala antes de parsear el body y compárala en tiempo constante.",
            "in": "header",
            "name": "X-MW-Signature",
            "required": true,
            "schema": {
              "examples": [
                "v1=FIRMA_HEX"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `key_id` de cada secreto con que se firmó (separados por coma durante una rotación).",
            "in": "header",
            "name": "X-MW-Key-Id",
            "required": true,
            "schema": {
              "examples": [
                "KEY_ID"
              ],
              "type": "string"
            }
          },
          {
            "description": "Segundos Unix del intento. Rechaza los que se alejan demasiado de tu reloj (protección contra replays).",
            "in": "header",
            "name": "X-MW-Timestamp",
            "required": true,
            "schema": {
              "examples": [
                "1792854492"
              ],
              "type": "string"
            }
          },
          {
            "description": "La entrega (un evento hacia una suscripción). Se repite en cada reintento.",
            "in": "header",
            "name": "X-MW-Delivery-Id",
            "required": true,
            "schema": {
              "examples": [
                "8a1d2c3e-0000-4000-8000-0000000000f1"
              ],
              "type": "string"
            }
          },
          {
            "description": "El `event_id` del evento: deduplica por él.",
            "in": "header",
            "name": "X-MW-Event-Id",
            "required": true,
            "schema": {
              "examples": [
                "e1f0c2d4-0000-4000-8000-000000001187"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "prueba": true
                },
                "event_id": "e1f0c2d4-0000-4000-8000-000000001187",
                "generation": 1,
                "instance_id": "8a1d2c3e-0000-4000-8000-0000000000a1",
                "occurred_at": "2026-10-24T15:08:12Z",
                "origin": "live",
                "received_at": "2026-10-24T15:08:13Z",
                "schema_version": 1,
                "seq": 1187,
                "type": "webhook.test"
              },
              "schema": {
                "$ref": "#/components/schemas/EventoWebhookTest"
              }
            }
          },
          "description": "El evento en su sobre (JSON).",
          "required": true
        },
        "responses": {
          "2XX": {
            "description": "Recibido: cualquier 2xx marca la entrega como entregada. Responde rápido y procesa aparte."
          },
          "default": {
            "description": "Cualquier otro status (o un timeout) es un intento fallido: el motor reintenta con backoff. Un 401 o un 403 suspende la suscripción hasta que la reactives (`PATCH /v1/subscriptions/{id}` con `estado: activa`)."
          }
        },
        "summary": "webhook.test: Una entrega de prueba.",
        "tags": [
          "Catálogo de eventos"
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AccionInteractiva": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "enum": [
              "reply",
              "copy",
              "url",
              "call",
              "pix",
              "list_row"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "seccion": {
            "type": "string"
          },
          "tarjeta": {
            "description": "La tarjeta del carrusel (desde 0).",
            "format": "int64",
            "type": "integer"
          },
          "titulo": {
            "type": "string"
          }
        },
        "required": [
          "accion",
          "titulo"
        ],
        "type": "object"
      },
      "AccionRespondida": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "description": "La acción del interactivo, si se correlacionó.",
            "enum": [
              "reply",
              "list_row",
              ""
            ],
            "type": "string"
          },
          "descripcion": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "indice": {
            "description": "El botón, si el formato lo informa (template_button_reply).",
            "format": "int64",
            "type": "integer"
          },
          "seccion": {
            "type": "string"
          },
          "tarjeta": {
            "format": "int64",
            "type": "integer"
          },
          "titulo": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "AceptadoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "aceptado": {
            "type": "boolean"
          }
        },
        "required": [
          "aceptado"
        ],
        "type": "object"
      },
      "ActualizacionesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "recibidas": {
            "description": "Cuántas publicaciones informó el servidor (las que cambiaron dejan newsletter.updates).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "recibidas"
        ],
        "type": "object"
      },
      "Alerta": {
        "additionalProperties": false,
        "properties": {
          "abierta_en": {
            "format": "date-time",
            "type": "string"
          },
          "cerrada_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "cierre": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "instancia_id": {
            "type": "string"
          },
          "motivo": {
            "type": "string"
          },
          "ocurrencias": {
            "format": "int64",
            "type": "integer"
          },
          "severidad": {
            "enum": [
              "critica",
              "advertencia"
            ],
            "type": "string"
          },
          "tipo": {
            "enum": [
              "instancia_caida",
              "sesion_cerrada",
              "reemplazada",
              "bloqueo_temporal",
              "cliente_desactualizado",
              "error_conexion"
            ],
            "type": "string"
          },
          "ultima_vez": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "instancia_id",
          "tipo",
          "severidad",
          "motivo",
          "ocurrencias",
          "abierta_en",
          "ultima_vez",
          "cerrada_en",
          "cierre"
        ],
        "type": "object"
      },
      "AppstateOutputBody": {
        "additionalProperties": false,
        "properties": {
          "colecciones": {
            "items": {
              "$ref": "#/components/schemas/Coleccion"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "colecciones"
        ],
        "type": "object"
      },
      "AreaServicio": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "description": "El nombre que le dio el negocio (una ciudad, un barrio), si lo dio.",
            "type": "string"
          },
          "latitud": {
            "format": "double",
            "type": "number"
          },
          "longitud": {
            "format": "double",
            "type": "number"
          },
          "radio_metros": {
            "description": "El radio del círculo, en metros.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "latitud",
          "longitud",
          "radio_metros"
        ],
        "type": "object"
      },
      "AudienciaEstado": {
        "additionalProperties": false,
        "properties": {
          "destinos": {
            "description": "En modo lista: teléfonos, JID de usuario o peer_ref de esta instancia.",
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 256,
            "type": [
              "array",
              "null"
            ]
          },
          "max_destinatarios": {
            "description": "El máximo de destinatarios que aceptas (no puede pasar el de Ajustes). Si la audiencia tiene más, no sale (audiencia_excedida).",
            "format": "int64",
            "maximum": 5000,
            "minimum": 1,
            "type": "integer"
          },
          "modo": {
            "description": "privacidad: la audiencia que dice la privacidad de status del número (la del teléfono); lista: solo estos destinos, que tienen que estar dentro de esa privacidad.",
            "enum": [
              "privacidad",
              "lista"
            ],
            "type": "string"
          },
          "privacidad": {
            "description": "En modo privacidad, la que esperas: contacts (mis contactos), allowlist (solo con…) o denylist (mis contactos excepto…). Si la del número es otra, no sale (privacidad_distinta).",
            "type": "string"
          }
        },
        "required": [
          "modo",
          "max_destinatarios"
        ],
        "type": "object"
      },
      "AudienciaEstadoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "destinatarios": {
            "description": "Cuántos contactos tiene esa audiencia ahora (sin contar quién no usa WhatsApp).",
            "format": "int64",
            "type": "integer"
          },
          "horas_retencion": {
            "description": "Cuánto guarda el motor un status recibido (nunca más que su vencimiento: 24 horas).",
            "format": "int64",
            "type": "integer"
          },
          "max_destinatarios_ajustes": {
            "description": "Lo más que puede declarar una publicación (Ajustes).",
            "format": "int64",
            "type": "integer"
          },
          "privacidad": {
            "description": "La privacidad de status del número (la del teléfono).",
            "enum": [
              "contacts",
              "allowlist",
              "denylist"
            ],
            "type": "string"
          }
        },
        "required": [
          "privacidad",
          "destinatarios",
          "max_destinatarios_ajustes",
          "horas_retencion"
        ],
        "type": "object"
      },
      "BloqueadosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "bloqueados": {
            "items": {
              "$ref": "#/components/schemas/BloqueoVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "bloqueados"
        ],
        "type": "object"
      },
      "BloqueoVista": {
        "additionalProperties": false,
        "properties": {
          "bloqueado": {
            "type": "boolean"
          },
          "cambio_en": {
            "format": "date-time",
            "type": "string"
          },
          "contacto": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "type": "string"
          },
          "telefono": {
            "type": "string"
          }
        },
        "required": [
          "contacto",
          "bloqueado",
          "cambio_en",
          "desde"
        ],
        "type": "object"
      },
      "Boton": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "description": "reply: responder (la respuesta llega como interactive.response); copy: copiar un código; url: abrir un enlace; call: abrir el marcador con un teléfono (no es una llamada del motor); pix: la información de pago PIX.",
            "enum": [
              "reply",
              "copy",
              "url",
              "call",
              "pix"
            ],
            "type": "string"
          },
          "codigo": {
            "description": "copy: el código que se copia.",
            "maxLength": 256,
            "type": "string"
          },
          "id": {
            "description": "reply: el ID que vuelve en la respuesta (único en el mensaje). El resto lo ignora WhatsApp: el motor no inventa un clic.",
            "maxLength": 200,
            "type": "string"
          },
          "pix": {
            "$ref": "#/components/schemas/PIX"
          },
          "telefono": {
            "description": "call: un número internacional.",
            "maxLength": 32,
            "type": "string"
          },
          "texto": {
            "description": "Lo que dice el botón (pix no lleva: lo pone WhatsApp).",
            "maxLength": 20,
            "type": "string"
          },
          "url": {
            "description": "url: un enlace http(s).",
            "maxLength": 2000,
            "type": "string"
          }
        },
        "required": [
          "accion"
        ],
        "type": "object"
      },
      "CambioPrivacidad": {
        "additionalProperties": false,
        "properties": {
          "opcion": {
            "description": "groupadd (quién te agrega a grupos), last (última vez), status (estados), profile (foto), readreceipts (confirmaciones de lectura), online (en línea), calladd (quién te llama), messages (quién te escribe), defense (protección avanzada), stickers.",
            "enum": [
              "groupadd",
              "last",
              "status",
              "profile",
              "readreceipts",
              "online",
              "calladd",
              "messages",
              "defense",
              "stickers"
            ],
            "type": "string"
          },
          "valor": {
            "description": "Los que acepta cada opción: groupadd, last, status y profile: all, contacts, contact_blacklist, none; readreceipts: all, none; online: all, match_last_seen; calladd: all, known; messages: all, contacts; defense: on_standard, off; stickers: contacts, contact_allowlist, none.",
            "enum": [
              "all",
              "contacts",
              "contact_blacklist",
              "none",
              "match_last_seen",
              "known",
              "on_standard",
              "off",
              "contact_allowlist"
            ],
            "type": "string"
          }
        },
        "required": [
          "opcion",
          "valor"
        ],
        "type": "object"
      },
      "CanalInvitacion": {
        "additionalProperties": false,
        "properties": {
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "descripcion": {
            "type": "string"
          },
          "estado": {
            "type": "string"
          },
          "jid": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "suscriptores": {
            "format": "int64",
            "type": "integer"
          },
          "verificado": {
            "type": "boolean"
          }
        },
        "required": [
          "jid",
          "nombre",
          "suscriptores",
          "verificado"
        ],
        "type": "object"
      },
      "CanalOutputBody": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/CanalWA"
          }
        },
        "required": [
          "canal"
        ],
        "type": "object"
      },
      "CanalRef": {
        "additionalProperties": false,
        "properties": {
          "enlace": {
            "description": "Solo para seguirlo: el enlace https://whatsapp.com/channel/… o su código.",
            "maxLength": 200,
            "type": "string"
          },
          "jid": {
            "description": "El JID del canal (…@newsletter).",
            "maxLength": 128,
            "type": "string"
          },
          "peer_ref": {
            "description": "El peer_ref del canal en esta instancia.",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CanalWA": {
        "additionalProperties": false,
        "properties": {
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "consultado_en": {
            "format": "date-time",
            "type": "string"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "descripcion": {
            "type": "string"
          },
          "en_vivo": {
            "description": "Ahora llegan en vivo (en_vivo_hasta todavía no pasó).",
            "type": "boolean"
          },
          "en_vivo_hasta": {
            "description": "Hasta cuándo llegan las vistas y reacciones en vivo (lo pidió el motor).",
            "format": "date-time",
            "type": "string"
          },
          "estado": {
            "description": "active, suspended o geosuspended (lo que dice WhatsApp).",
            "type": "string"
          },
          "foto_id": {
            "type": "string"
          },
          "invitacion": {
            "description": "El enlace de invitación (https://whatsapp.com/channel/…).",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "nombre_en": {
            "format": "date-time",
            "type": "string"
          },
          "reacciones": {
            "description": "Qué reacciones permite: all, basic, none o blocklist.",
            "type": "string"
          },
          "rol": {
            "description": "El rol del número: owner y admin publican; subscriber lo sigue; guest no (los permisos los decide WhatsApp).",
            "enum": [
              "owner",
              "admin",
              "subscriber",
              "guest",
              ""
            ],
            "type": "string"
          },
          "siguiendo": {
            "description": "El número lo sigue o lo administra.",
            "type": "boolean"
          },
          "silenciado": {
            "type": "boolean"
          },
          "suscriptores": {
            "description": "Lo último que informó WhatsApp.",
            "format": "int64",
            "type": "integer"
          },
          "verificado": {
            "type": "boolean"
          },
          "version": {
            "description": "Sube con cada cambio de esta fila.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "canal",
          "nombre",
          "descripcion",
          "verificado",
          "suscriptores",
          "rol",
          "siguiendo",
          "silenciado",
          "en_vivo",
          "version",
          "actualizado_en"
        ],
        "type": "object"
      },
      "CanalesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "canales": {
            "items": {
              "$ref": "#/components/schemas/CanalWA"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "canales",
          "has_more"
        ],
        "type": "object"
      },
      "CapabilitiesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "avisos": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "capacidades": {
            "items": {
              "$ref": "#/components/schemas/Capacidad"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "contrato": {
            "examples": [
              "1.0.0"
            ],
            "type": "string"
          },
          "eventos": {
            "$ref": "#/components/schemas/ContratoEventos"
          },
          "proveedores": {
            "items": {
              "$ref": "#/components/schemas/ProveedorV1"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "scopes": {
            "description": "Los scopes de esta key.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "contrato",
          "eventos",
          "proveedores",
          "capacidades",
          "scopes",
          "avisos"
        ],
        "type": "object"
      },
      "Capacidad": {
        "additionalProperties": false,
        "properties": {
          "aviso": {
            "type": "string"
          },
          "clave": {
            "type": "string"
          },
          "estado": {
            "enum": [
              "disponible",
              "planificada",
              "experimental",
              "no_soportada"
            ],
            "type": "string"
          },
          "etapa": {
            "type": "string"
          }
        },
        "required": [
          "clave",
          "estado",
          "etapa"
        ],
        "type": "object"
      },
      "CatalogoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "completitud": {
            "description": "Siempre una página: el motor no recorre el catálogo entero.",
            "enum": [
              "pagina"
            ],
            "type": "string"
          },
          "consulta_id": {
            "description": "La consulta remota que leyó esto (la de su evento query.completed).",
            "type": "string"
          },
          "consultado_en": {
            "format": "date-time",
            "type": "string"
          },
          "continuacion": {
            "description": "no_informada: WhatsApp no mandó una continuación. Que el catálogo terminó no está verificado todavía (prueba manual): has_more es null, no false.",
            "enum": [
              "informada",
              "no_informada"
            ],
            "type": "string"
          },
          "cuota": {
            "$ref": "#/components/schemas/CuotaComercio"
          },
          "fresca_hasta": {
            "description": "Hasta cuándo una consulta igual se responde con esta lectura.",
            "format": "date-time",
            "type": "string"
          },
          "has_more": {
            "description": "true si hay una continuación; null si no se informó (desconocido, nunca false inventado).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "limit": {
            "format": "int64",
            "type": "integer"
          },
          "negocio_jid": {
            "type": "string"
          },
          "next_cursor": {
            "description": "Opaco, firmado y atado a la app, la instancia, este número vinculado, el negocio y el límite.",
            "type": [
              "string",
              "null"
            ]
          },
          "origen": {
            "description": "whatsapp: se consultó ahora; cache: es la misma lectura de hace poco, sin volver a WhatsApp.",
            "enum": [
              "whatsapp",
              "cache"
            ],
            "type": "string"
          },
          "paginacion": {
            "description": "La continuación es la de WhatsApp (paging/after).",
            "enum": [
              "proveedor"
            ],
            "type": "string"
          },
          "productos": {
            "description": "Los que vinieron en esta página (una lista vacía es la respuesta real del servidor, de causa desconocida).",
            "items": {
              "$ref": "#/components/schemas/ProductoComercial"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "propio": {
            "description": "Es el catálogo del número de la instancia.",
            "type": "boolean"
          },
          "total": {
            "description": "Siempre null: WhatsApp no informa un total (no se cuenta esta página).",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "vence_en": {
            "description": "Hasta cuándo sirve su next_cursor.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "cuota",
          "negocio_jid",
          "propio",
          "completitud",
          "total",
          "paginacion",
          "continuacion",
          "has_more",
          "next_cursor",
          "limit",
          "productos",
          "consulta_id",
          "origen",
          "consultado_en",
          "fresca_hasta",
          "vence_en"
        ],
        "type": "object"
      },
      "CategoriaComercial": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "nombre"
        ],
        "type": "object"
      },
      "ChatsOutputBody": {
        "additionalProperties": false,
        "properties": {
          "chats": {
            "items": {
              "$ref": "#/components/schemas/EstadoChat"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "description": "El cursor de la página siguiente (vacío: no hay más).",
            "type": "string"
          }
        },
        "required": [
          "chats",
          "has_more"
        ],
        "type": "object"
      },
      "Cita": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "description": "JID de quien lo escribió (en grupos).",
            "maxLength": 128,
            "type": "string"
          },
          "provider_id": {
            "description": "El provider_id del mensaje citado.",
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "provider_id"
        ],
        "type": "object"
      },
      "ClaveMensaje": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "description": "En un grupo, el JID de quien lo escribió (si no es propio).",
            "maxLength": 128,
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "momento": {
            "description": "Su timestamp en WhatsApp.",
            "format": "date-time",
            "type": "string"
          },
          "provider_id": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "provider_id",
          "from_me",
          "momento"
        ],
        "type": "object"
      },
      "Coleccion": {
        "additionalProperties": false,
        "properties": {
          "coleccion": {
            "enum": [
              "regular",
              "regular_low",
              "regular_high"
            ],
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "estado": {
            "enum": [
              "pendiente",
              "al_dia",
              "error",
              "clave_faltante"
            ],
            "type": "string"
          },
          "proximo_intento_en": {
            "format": "date-time",
            "type": "string"
          },
          "recuperacion_en": {
            "description": "Cuándo el motor le pidió al teléfono una copia (una clave que no llegaba).",
            "format": "date-time",
            "type": "string"
          },
          "reintentos": {
            "format": "int64",
            "type": "integer"
          },
          "requiere_full": {
            "description": "La próxima sincronización es completa (nunca se hizo, un cambio no se pudo aceptar o la pidió un operador).",
            "type": "boolean"
          },
          "ultimo_full_en": {
            "format": "date-time",
            "type": "string"
          },
          "ultimo_sync_en": {
            "format": "date-time",
            "type": "string"
          },
          "version": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "coleccion",
          "estado",
          "version",
          "reintentos",
          "requiere_full"
        ],
        "type": "object"
      },
      "ColeccionVista": {
        "additionalProperties": false,
        "properties": {
          "alcanza_limite": {
            "description": "Trajo tantos productos como item_limit: puede tener más.",
            "type": "boolean"
          },
          "completitud_productos": {
            "description": "El protocolo observado no informa si vinieron todos sus productos.",
            "enum": [
              "desconocida"
            ],
            "type": "string"
          },
          "id": {
            "description": "Opaco y del negocio.",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "productos": {
            "items": {
              "$ref": "#/components/schemas/ProductoComercial"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "puede_apelar": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "revision": {
            "type": "string"
          }
        },
        "required": [
          "completitud_productos",
          "alcanza_limite",
          "id",
          "puede_apelar",
          "productos"
        ],
        "type": "object"
      },
      "ColeccionesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "colecciones": {
            "items": {
              "$ref": "#/components/schemas/ColeccionVista"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "collection_limit": {
            "format": "int64",
            "type": "integer"
          },
          "completitud": {
            "description": "La vista es la primera que da WhatsApp con los dos límites; no se sabe si es completa.",
            "enum": [
              "desconocida"
            ],
            "type": "string"
          },
          "consulta_id": {
            "description": "La consulta remota que leyó esto (la de su evento query.completed).",
            "type": "string"
          },
          "consultado_en": {
            "format": "date-time",
            "type": "string"
          },
          "continuacion_remota": {
            "description": "Siempre false: la continuación de las colecciones en WhatsApp no está implementada (brecha conocida de P056).",
            "type": "boolean"
          },
          "cuota": {
            "$ref": "#/components/schemas/CuotaComercio"
          },
          "fresca_hasta": {
            "description": "Hasta cuándo una consulta igual se responde con esta lectura.",
            "format": "date-time",
            "type": "string"
          },
          "has_more": {
            "description": "Hay más colecciones en la vista local (no en WhatsApp).",
            "type": "boolean"
          },
          "item_limit": {
            "format": "int64",
            "type": "integer"
          },
          "limit": {
            "format": "int64",
            "type": "integer"
          },
          "negocio_jid": {
            "type": "string"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "origen": {
            "description": "whatsapp: se consultó ahora; cache: es la misma lectura de hace poco, sin volver a WhatsApp.",
            "enum": [
              "whatsapp",
              "cache"
            ],
            "type": "string"
          },
          "paginacion": {
            "description": "next_cursor pagina la vista guardada, no a WhatsApp.",
            "enum": [
              "snapshot_local"
            ],
            "type": "string"
          },
          "paging_recibido": {
            "description": "La respuesta traía una señal de continuación que el motor todavía no sabe seguir.",
            "type": "boolean"
          },
          "posible_truncamiento": {
            "description": "La vista alcanzó collection_limit o alguna colección alcanzó item_limit: puede haber más.",
            "type": "boolean"
          },
          "propio": {
            "type": "boolean"
          },
          "proveedor_has_more": {
            "description": "Siempre null: WhatsApp no informa si hay más colecciones o productos.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "total_vista": {
            "description": "Colecciones en la vista guardada (no el total en WhatsApp).",
            "format": "int64",
            "type": "integer"
          },
          "vence_en": {
            "description": "Hasta cuándo sirve su next_cursor.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "cuota",
          "negocio_jid",
          "propio",
          "completitud",
          "paginacion",
          "continuacion_remota",
          "proveedor_has_more",
          "paging_recibido",
          "posible_truncamiento",
          "has_more",
          "next_cursor",
          "collection_limit",
          "item_limit",
          "limit",
          "total_vista",
          "colecciones",
          "consulta_id",
          "origen",
          "consultado_en",
          "fresca_hasta",
          "vence_en"
        ],
        "type": "object"
      },
      "Comando": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "error_code": {
            "type": "string"
          },
          "expires_at": {
            "format": "date-time",
            "type": "string"
          },
          "generation": {
            "format": "int64",
            "type": "integer"
          },
          "idempotency_key": {
            "examples": [
              "crm-envio-0001"
            ],
            "type": "string"
          },
          "instance_id": {
            "type": "string"
          },
          "media": {
            "$ref": "#/components/schemas/MedioComando"
          },
          "next_try": {
            "description": "Cuándo se intenta (cola de envío o reintento después de un error previo).",
            "format": "date-time",
            "type": "string"
          },
          "provider_message_id": {
            "description": "El ID fijo del mensaje en WhatsApp: se guarda antes de enviarlo y no cambia en un reintento.",
            "type": "string"
          },
          "result": {
            "description": "Lo que devolvió WhatsApp: el grupo creado, el enlace, los resultados por participante…"
          },
          "sent_at": {
            "description": "Cuándo lo aceptó el servidor de WhatsApp (no es entregado ni leído).",
            "format": "date-time",
            "type": "string"
          },
          "server_code": {
            "description": "Si falló porque WhatsApp lo rechazó: el código que dio el servidor (p. ej. 400), sin su texto.",
            "format": "int64",
            "type": "integer"
          },
          "server_origin": {
            "description": "De dónde vino server_code (iq: un IQ; mex: una mutación MEX).",
            "type": "string"
          },
          "stage": {
            "description": "Dónde falló o quedó ambiguo: previa (no salió), servidor (lo rechazó) o frontera (pudo salir: ambiguo).",
            "enum": [
              "previa",
              "servidor",
              "frontera",
              ""
            ],
            "type": "string"
          },
          "status": {
            "examples": [
              "en_cola"
            ],
            "type": "string"
          },
          "type": {
            "examples": [
              "message.text"
            ],
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "command_id",
          "instance_id",
          "idempotency_key",
          "type",
          "generation",
          "status",
          "created_at",
          "updated_at"
        ],
        "type": "object"
      },
      "ComunidadVista": {
        "additionalProperties": false,
        "properties": {
          "comunidad": {
            "$ref": "#/components/schemas/GrupoWA"
          },
          "consultado_en": {
            "format": "date-time",
            "type": "string"
          },
          "subgrupos": {
            "items": {
              "$ref": "#/components/schemas/SubgrupoVista"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "version": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "comunidad",
          "subgrupos",
          "version"
        ],
        "type": "object"
      },
      "ConfigInstancia": {
        "additionalProperties": false,
        "properties": {
          "historial_dias": {
            "format": "int64",
            "maximum": 3650,
            "minimum": 1,
            "type": "integer"
          },
          "historial_importar": {
            "type": "boolean"
          },
          "historial_medios": {
            "type": "boolean"
          },
          "historial_mensajes": {
            "format": "int64",
            "maximum": 100000,
            "minimum": 1,
            "type": "integer"
          },
          "mensaje_rechazo": {
            "maxLength": 1000,
            "type": "string"
          },
          "mensajes_por_segundo": {
            "format": "int64",
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "rafaga": {
            "format": "int64",
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "rechazar_llamadas": {
            "type": "boolean"
          },
          "reconexion_automatica": {
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "reconexion_automatica"
        ],
        "type": "object"
      },
      "ConfigPatch": {
        "additionalProperties": false,
        "properties": {
          "historial_dias": {
            "description": "Lo más viejo que se importa, en días (si no, el de Ajustes).",
            "format": "int64",
            "maximum": 3650,
            "minimum": 1,
            "type": "integer"
          },
          "historial_importar": {
            "description": "MW8a: importar los mensajes del historial (si no, el de Ajustes, apagado de fábrica). Los metadatos y el protocolo se procesan siempre.",
            "type": "boolean"
          },
          "historial_medios": {
            "description": "Descargar la multimedia de lo importado (si no, solo sus metadatos).",
            "type": "boolean"
          },
          "historial_mensajes": {
            "description": "La cuota de mensajes de cada trabajo de historial (si no, la de Ajustes).",
            "format": "int64",
            "maximum": 100000,
            "minimum": 1,
            "type": "integer"
          },
          "mensaje_rechazo": {
            "description": "Texto que se manda a quien llamó, por el mismo outbox, al rechazar solo. Si no viene, no cambia (mandar la configuración vieja sin él lo deja como estaba); null o vacío lo borra.",
            "maxLength": 1000,
            "type": [
              "string",
              "null"
            ]
          },
          "mensajes_por_segundo": {
            "description": "Ritmo de envío propio (si no, el de Ajustes).",
            "format": "int64",
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "rafaga": {
            "description": "Envíos seguidos permitidos (si no, el de Ajustes).",
            "format": "int64",
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "rechazar_llamadas": {
            "description": "MW5b: rechazar solas las llamadas entrantes (el motor no atiende voz ni vídeo).",
            "type": "boolean"
          },
          "reconexion_automatica": {
            "description": "Si el motor vuelve a conectar la instancia cuando se cae sin quererlo.",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "Confirmar-passkeyRequest": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          }
        },
        "required": [
          "generacion"
        ],
        "type": "object"
      },
      "ConsultaNumerosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "cuota": {
            "$ref": "#/components/schemas/Cuota"
          },
          "resultados": {
            "items": {
              "$ref": "#/components/schemas/ResultadoNumero"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "resultados",
          "cuota"
        ],
        "type": "object"
      },
      "Contacto": {
        "additionalProperties": false,
        "properties": {
          "nombre": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "telefonos": {
            "items": {
              "type": "string"
            },
            "maxItems": 5,
            "type": [
              "array",
              "null"
            ]
          },
          "vcard": {
            "maxLength": 10000,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "ContactoVista": {
        "additionalProperties": false,
        "properties": {
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "contacto": {
            "$ref": "#/components/schemas/Peer"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "en_libreta": {
            "description": "Guardado en la libreta del teléfono del número.",
            "type": "boolean"
          },
          "foto_id": {
            "description": "El ID de su foto de perfil (la imagen se consulta aparte).",
            "type": "string"
          },
          "libreta_en": {
            "format": "date-time",
            "type": "string"
          },
          "nombre": {
            "description": "Cómo lo guardó el teléfono (nombre completo).",
            "type": "string"
          },
          "nombre_negocio": {
            "description": "El nombre verificado de una cuenta de WhatsApp Business.",
            "type": "string"
          },
          "primer_nombre": {
            "type": "string"
          },
          "push_name": {
            "description": "El nombre que manda el contacto.",
            "type": "string"
          },
          "recado": {
            "description": "Su «info» (about), si lo comparte.",
            "type": "string"
          },
          "telefono": {
            "description": "El teléfono de su alias PN comprobado, si el motor lo conoce. Un LID nunca se convierte en teléfono.",
            "type": "string"
          }
        },
        "required": [
          "contacto",
          "en_libreta",
          "actualizado_en",
          "creado_en"
        ],
        "type": "object"
      },
      "ContactosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "contactos": {
            "items": {
              "$ref": "#/components/schemas/ContactoVista"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "contactos",
          "has_more"
        ],
        "type": "object"
      },
      "ContadorVista": {
        "additionalProperties": false,
        "properties": {
          "provider_id": {
            "type": "string"
          },
          "reacciones": {
            "additionalProperties": {
              "format": "int64",
              "type": "integer"
            },
            "type": "object"
          },
          "server_id": {
            "format": "int64",
            "type": "integer"
          },
          "vistas": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "server_id",
          "vistas",
          "reacciones"
        ],
        "type": "object"
      },
      "ContratoEventos": {
        "additionalProperties": false,
        "properties": {
          "conexiones_por_app": {
            "format": "int64",
            "type": "integer"
          },
          "cursor": {
            "description": "Cómo se reanuda un stream.",
            "type": "string"
          },
          "dias_reanudacion": {
            "description": "Un cursor con eventos sin leer más viejos que esto recibe 410 con primer_cursor.",
            "format": "int64",
            "type": "integer"
          },
          "keepalive_segundos": {
            "format": "int64",
            "type": "integer"
          },
          "schema_versions": {
            "description": "Los schema_version de los envelopes que puede mandar.",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "transportes": {
            "examples": [
              [
                "webhook",
                "sse",
                "websocket"
              ]
            ],
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "version": {
            "description": "La vigente: la de cada stream si no se pide otra con ?contrato=.",
            "examples": [
              "1"
            ],
            "type": "string"
          },
          "versiones_soportadas": {
            "examples": [
              [
                "1"
              ]
            ],
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "version",
          "versiones_soportadas",
          "schema_versions",
          "transportes",
          "cursor",
          "conexiones_por_app",
          "keepalive_segundos",
          "dias_reanudacion"
        ],
        "type": "object"
      },
      "Crear-instanciaRequest": {
        "additionalProperties": false,
        "properties": {
          "nombre": {
            "examples": [
              "Ventas Lima"
            ],
            "maxLength": 120,
            "minLength": 1,
            "type": "string"
          },
          "owner_ref": {
            "description": "Referencia opaca del dueño dentro de tu app.",
            "examples": [
              "empresa-42"
            ],
            "maxLength": 200,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CrearCanal": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "maxLength": 2048,
            "type": "string"
          },
          "foto_media_id": {
            "description": "Un JPEG subido a esta instancia, listo (hasta 2 MB, de 192 a 2048 píxeles por lado).",
            "type": "string"
          },
          "nombre": {
            "maxLength": 100,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CrearComunidad": {
        "additionalProperties": false,
        "properties": {
          "aprobacion": {
            "description": "Entrar a la comunidad exige la aprobación de un administrador. Solo cambia el pedido con la forma sdk de Ajustes: las otras crean la comunidad como WhatsApp Web, con la aprobación para entrar a sus grupos (default_membership_approval_mode=request_required).",
            "type": "boolean"
          },
          "descripcion": {
            "maxLength": 2048,
            "type": "string"
          },
          "nombre": {
            "maxLength": 25,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CrearGrupo": {
        "additionalProperties": false,
        "properties": {
          "anuncio": {
            "description": "Solo los administradores escriben.",
            "type": "boolean"
          },
          "aprobacion": {
            "description": "Entrar exige la aprobación de un administrador.",
            "type": "boolean"
          },
          "bloqueado": {
            "description": "Solo los administradores editan la información.",
            "type": "boolean"
          },
          "comunidad": {
            "$ref": "#/components/schemas/GrupoRef"
          },
          "efimero_seg": {
            "description": "0, 86400, 604800 o 7776000.",
            "format": "int64",
            "maximum": 7776000,
            "minimum": 0,
            "type": "integer"
          },
          "modo_agregar": {
            "description": "Quién puede agregar participantes (de fábrica, todos).",
            "enum": [
              "admin_add",
              "all_member_add",
              ""
            ],
            "type": "string"
          },
          "nombre": {
            "description": "Hasta 25 caracteres (el límite de WhatsApp).",
            "maxLength": 25,
            "minLength": 1,
            "type": "string"
          },
          "participantes": {
            "description": "Los que se agregan al crearlo (el número entra solo).",
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 256,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CuerpoAccionChat": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "description": "pin/unpin (chat.pin), archive/unarchive (chat.archive), mute/unmute (chat.mute), mark_read/mark_unread (chat.mark_read), star/unstar un mensaje (chat.star) y delete (chat.delete, irreversible).",
            "enum": [
              "pin",
              "unpin",
              "archive",
              "unarchive",
              "mute",
              "unmute",
              "mark_read",
              "mark_unread",
              "star",
              "unstar",
              "delete"
            ],
            "type": "string"
          },
          "borrar_medios": {
            "description": "delete: borrar también los archivos del chat en el teléfono.",
            "type": "boolean"
          },
          "confirmar_irreversible": {
            "description": "delete: tiene que ser true (no se puede deshacer).",
            "type": "boolean"
          },
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "duracion_seg": {
            "description": "mute: cuánto (0 o vacío: para siempre).",
            "format": "int64",
            "maximum": 31536000,
            "minimum": 0,
            "type": "integer"
          },
          "objetivo": {
            "$ref": "#/components/schemas/Objetivo"
          },
          "ultimo_mensaje": {
            "$ref": "#/components/schemas/ClaveMensaje"
          }
        },
        "required": [
          "accion",
          "destino"
        ],
        "type": "object"
      },
      "CuerpoActualizaciones": {
        "additionalProperties": false,
        "properties": {
          "desde": {
            "description": "Las que cambiaron desde este momento.",
            "format": "date-time",
            "type": "string"
          },
          "despues_de": {
            "description": "Las publicaciones con un server_id mayor que este.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CuerpoAjusteGrupo": {
        "additionalProperties": false,
        "properties": {
          "ajuste": {
            "enum": [
              "announce",
              "locked",
              "approval",
              "member_add"
            ],
            "type": "string"
          },
          "modo": {
            "enum": [
              "admin_add",
              "all_member_add",
              ""
            ],
            "type": "string"
          },
          "valor": {
            "type": "boolean"
          }
        },
        "required": [
          "ajuste"
        ],
        "type": "object"
      },
      "CuerpoAsociacion": {
        "additionalProperties": false,
        "properties": {
          "asociar": {
            "description": "true: ponerla; false: quitarla.",
            "type": "boolean"
          },
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "objetivo": {
            "$ref": "#/components/schemas/Objetivo"
          }
        },
        "required": [
          "destino",
          "asociar"
        ],
        "type": "object"
      },
      "CuerpoBloqueo": {
        "additionalProperties": false,
        "properties": {
          "bloquear": {
            "description": "true: bloquear; false: desbloquear.",
            "type": "boolean"
          },
          "destino": {
            "$ref": "#/components/schemas/Destino"
          }
        },
        "required": [
          "destino",
          "bloquear"
        ],
        "type": "object"
      },
      "CuerpoComando": {
        "additionalProperties": false,
        "properties": {
          "correlation_id": {
            "maxLength": 200,
            "type": "string"
          },
          "expires_at": {
            "description": "Si no se ejecutó antes, no se ejecuta.",
            "format": "date-time",
            "type": "string"
          },
          "payload": {
            "$ref": "#/components/schemas/MotivoOpcional"
          },
          "type": {
            "description": "reconnect: cierra y vuelve a abrir el socket. disconnect: lo cierra hasta que pidas reconectar (o hasta que el motor reinicie). pause: lo cierra y la instancia queda pausada también después de reiniciar; resume la vuelve a activar. logout: desvincula el número (avisa a WhatsApp si la sesión está autenticada). archive: desvincula y archiva (igual que DELETE).",
            "enum": [
              "instance.reconnect",
              "instance.disconnect",
              "instance.pause",
              "instance.resume",
              "instance.logout",
              "instance.archive"
            ],
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "type": "object"
      },
      "CuerpoConsultaNumeros": {
        "additionalProperties": false,
        "properties": {
          "telefonos": {
            "description": "Números internacionales (con o sin +). Repetidos cuentan una vez.",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "telefonos"
        ],
        "type": "object"
      },
      "CuerpoDescripcionGrupo": {
        "additionalProperties": false,
        "properties": {
          "texto": {
            "description": "Vacío la borra.",
            "maxLength": 2048,
            "type": "string"
          }
        },
        "required": [
          "texto"
        ],
        "type": "object"
      },
      "CuerpoEmparejar": {
        "additionalProperties": false,
        "properties": {
          "generacion_esperada": {
            "description": "Si viene y no coincide con la actual, 409.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "modo": {
            "description": "qr: dibuja el QR. codigo: WhatsApp manda un código de 8 caracteres para escribir en el teléfono.",
            "enum": [
              "qr",
              "codigo"
            ],
            "examples": [
              "qr"
            ],
            "type": "string"
          },
          "telefono": {
            "description": "Solo en modo codigo: el número completo, empezando por + y el código de país. Sin el + (o con un código de país que no existe) es 422.",
            "examples": [
              "+NUMERO_DE_TU_TELEFONO"
            ],
            "maxLength": 32,
            "type": "string"
          }
        },
        "required": [
          "modo"
        ],
        "type": "object"
      },
      "CuerpoEnlace": {
        "additionalProperties": false,
        "properties": {
          "enlace": {
            "description": "El enlace https://chat.whatsapp.com/… o solo su código.",
            "maxLength": 200,
            "minLength": 4,
            "type": "string"
          }
        },
        "required": [
          "enlace"
        ],
        "type": "object"
      },
      "CuerpoEnlaceCanal": {
        "additionalProperties": false,
        "properties": {
          "enlace": {
            "description": "El enlace https://whatsapp.com/channel/… o solo su código.",
            "maxLength": 200,
            "minLength": 4,
            "type": "string"
          }
        },
        "required": [
          "enlace"
        ],
        "type": "object"
      },
      "CuerpoEnviarInvitacion": {
        "additionalProperties": false,
        "properties": {
          "destinos": {
            "description": "A quiénes se manda (cada uno, un mensaje de texto por el outbox).",
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 20,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          },
          "texto": {
            "description": "Lo que va antes del enlace (de fábrica, una invitación genérica).",
            "maxLength": 1000,
            "type": "string"
          }
        },
        "required": [
          "destinos"
        ],
        "type": "object"
      },
      "CuerpoEstado": {
        "additionalProperties": false,
        "properties": {
          "audiencia": {
            "$ref": "#/components/schemas/AudienciaEstado"
          },
          "correlation_id": {
            "maxLength": 200,
            "type": "string"
          },
          "expires_at": {
            "description": "Si no salió antes, no sale (fallido: comando_vencido).",
            "format": "date-time",
            "type": "string"
          },
          "fondo": {
            "description": "text: el color de fondo, #RRGGBB.",
            "type": "string"
          },
          "medio": {
            "$ref": "#/components/schemas/MedioRef"
          },
          "texto": {
            "description": "El texto (text, obligatorio) o el caption (image y video).",
            "maxLength": 700,
            "type": "string"
          },
          "tipo": {
            "default": "text",
            "description": "text (por omisión), image o video.",
            "enum": [
              "text",
              "image",
              "video"
            ],
            "type": "string"
          }
        },
        "required": [
          "audiencia"
        ],
        "type": "object"
      },
      "CuerpoEtiquetaCambio": {
        "additionalProperties": false,
        "properties": {
          "color": {
            "format": "int64",
            "maximum": 19,
            "minimum": 0,
            "type": "integer"
          },
          "nombre": {
            "maxLength": 100,
            "type": "string"
          }
        },
        "type": "object"
      },
      "CuerpoEtiquetaNueva": {
        "additionalProperties": false,
        "properties": {
          "color": {
            "description": "El índice de la paleta de WhatsApp (0 a 19; por omisión 0).",
            "format": "int64",
            "maximum": 19,
            "minimum": 0,
            "type": "integer"
          },
          "nombre": {
            "maxLength": 100,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CuerpoFoto": {
        "additionalProperties": false,
        "properties": {
          "media_id": {
            "description": "Un JPEG subido a esta instancia (POST /v1/instances/{id}/media/uploads), listo.",
            "type": "string"
          }
        },
        "required": [
          "media_id"
        ],
        "type": "object"
      },
      "CuerpoFotoContacto": {
        "additionalProperties": false,
        "properties": {
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "vista_previa": {
            "description": "La miniatura en vez de la foto completa.",
            "type": "boolean"
          }
        },
        "required": [
          "destino"
        ],
        "type": "object"
      },
      "CuerpoInfoContactos": {
        "additionalProperties": false,
        "properties": {
          "destinos": {
            "description": "Usuarios (teléfono, JID de usuario o peer_ref), no grupos.",
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 50,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "destinos"
        ],
        "type": "object"
      },
      "CuerpoLectura": {
        "additionalProperties": false,
        "properties": {
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "hasta": {
            "description": "O todos los recibidos de ese chat hasta este momento (los que no estaban leídos).",
            "format": "date-time",
            "type": "string"
          },
          "provider_ids": {
            "description": "Los mensajes recibidos de ese chat que se marcan.",
            "items": {
              "type": "string"
            },
            "maxItems": 100,
            "type": [
              "array",
              "null"
            ]
          },
          "reproducido": {
            "description": "Marcar como reproducidos (notas de voz y vídeos; distinto de leído).",
            "type": "boolean"
          }
        },
        "required": [
          "destino"
        ],
        "type": "object"
      },
      "CuerpoMensaje": {
        "additionalProperties": false,
        "properties": {
          "cita": {
            "$ref": "#/components/schemas/Cita"
          },
          "contactos": {
            "description": "contacts: de 1 a 10, con teléfonos (el motor arma la vCard) o una vCard propia (se valida).",
            "items": {
              "$ref": "#/components/schemas/Contacto"
            },
            "maxItems": 10,
            "type": [
              "array",
              "null"
            ]
          },
          "correlation_id": {
            "maxLength": 200,
            "type": "string"
          },
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "emoji": {
            "description": "reaction: el emoji; vacío quita la reacción.",
            "maxLength": 32,
            "type": "string"
          },
          "expires_at": {
            "description": "Si no se envió antes, no se envía (fallido: comando_vencido).",
            "format": "date-time",
            "type": "string"
          },
          "generacion_esperada": {
            "description": "Si viene y la instancia se volvió a vincular, 409.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "interactivo": {
            "$ref": "#/components/schemas/Interactivo"
          },
          "medio": {
            "$ref": "#/components/schemas/MedioRef"
          },
          "menciones": {
            "description": "Los mencionados, como el destino: un teléfono internacional (+número), un JID de usuario o un peer_ref de esta instancia (el motor los resuelve a su JID). El texto debería nombrarlos con @número. Una inválida es 422 mencion_invalida.",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "type": [
              "array",
              "null"
            ]
          },
          "multiple": {
            "description": "poll: se puede elegir más de una opción.",
            "type": "boolean"
          },
          "objetivo": {
            "$ref": "#/components/schemas/Objetivo"
          },
          "opciones": {
            "description": "poll: de 2 a 12 opciones distintas (hasta 100 caracteres).",
            "items": {
              "type": "string"
            },
            "maxItems": 12,
            "type": [
              "array",
              "null"
            ]
          },
          "pregunta": {
            "description": "poll: la pregunta.",
            "maxLength": 255,
            "type": "string"
          },
          "segundos": {
            "description": "disappearing: 0 (desactivado), 24 h, 7 días o 90 días.",
            "enum": [
              0,
              86400,
              604800,
              7776000
            ],
            "format": "int64",
            "type": "integer"
          },
          "texto": {
            "description": "El mensaje (text y edit, obligatorio) o el caption (image, video y document: hasta 1024). Un audio no lleva texto.",
            "examples": [
              "Hola, tu pedido salió hoy."
            ],
            "maxLength": 4096,
            "type": "string"
          },
          "tipo": {
            "default": "text",
            "description": "text (por omisión), image, video, document, audio, un subtipo con conversión (ptt, ptv, sticker, gif) o, desde la MW5: location, contacts, reaction, edit, revoke (borrar para todos), forward, disappearing (temporizador de mensajes efímeros del chat) y poll (encuesta); desde la MW10, interactive (botones, lista o carrusel: no garantizado en números no oficiales).",
            "enum": [
              "text",
              "image",
              "video",
              "document",
              "audio",
              "ptt",
              "ptv",
              "sticker",
              "gif",
              "location",
              "contacts",
              "reaction",
              "edit",
              "revoke",
              "forward",
              "disappearing",
              "poll",
              "interactive"
            ],
            "type": "string"
          },
          "ubicacion": {
            "$ref": "#/components/schemas/Ubicacion"
          },
          "vista_previa": {
            "$ref": "#/components/schemas/VistaPrevia"
          }
        },
        "required": [
          "destino"
        ],
        "type": "object"
      },
      "CuerpoNombre": {
        "additionalProperties": false,
        "properties": {
          "nombre": {
            "maxLength": 25,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CuerpoNombreGrupo": {
        "additionalProperties": false,
        "properties": {
          "nombre": {
            "description": "Hasta 25 caracteres (el límite de WhatsApp).",
            "maxLength": 25,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "nombre"
        ],
        "type": "object"
      },
      "CuerpoParticipantes": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "enum": [
              "add",
              "remove",
              "promote",
              "demote"
            ],
            "type": "string"
          },
          "participantes": {
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 50,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "accion",
          "participantes"
        ],
        "type": "object"
      },
      "CuerpoPatch": {
        "additionalProperties": false,
        "properties": {
          "config": {
            "$ref": "#/components/schemas/ConfigPatch"
          },
          "nombre": {
            "maxLength": 120,
            "minLength": 1,
            "type": "string"
          },
          "version_esperada": {
            "description": "Si viene y no coincide con la actual, 409.",
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CuerpoPatchSuscripcion": {
        "additionalProperties": false,
        "properties": {
          "estado": {
            "description": "activa también reactiva una suscripción suspendida (y cierra su alerta).",
            "enum": [
              "activa",
              "pausada"
            ],
            "type": "string"
          },
          "instancias": {
            "items": {
              "type": "string"
            },
            "maxItems": 200,
            "type": "array"
          },
          "nombre": {
            "maxLength": 120,
            "minLength": 1,
            "type": "string"
          },
          "ordenado": {
            "type": "boolean"
          },
          "tipos": {
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "url": {
            "maxLength": 2000,
            "minLength": 8,
            "type": "string"
          },
          "version_esperada": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CuerpoPedidoHistorial": {
        "additionalProperties": false,
        "properties": {
          "cantidad": {
            "description": "De fábrica, 50.",
            "format": "int64",
            "maximum": 50,
            "minimum": 1,
            "type": "integer"
          },
          "destino": {
            "$ref": "#/components/schemas/Destino"
          }
        },
        "required": [
          "destino"
        ],
        "type": "object"
      },
      "CuerpoPresencia": {
        "additionalProperties": false,
        "properties": {
          "disponible": {
            "description": "true: en línea; false: fuera de línea.",
            "type": "boolean"
          }
        },
        "required": [
          "disponible"
        ],
        "type": "object"
      },
      "CuerpoPresenciaChat": {
        "additionalProperties": false,
        "properties": {
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "estado": {
            "enum": [
              "escribiendo",
              "grabando",
              "pausado"
            ],
            "type": "string"
          }
        },
        "required": [
          "destino",
          "estado"
        ],
        "type": "object"
      },
      "CuerpoProxyInstancia": {
        "additionalProperties": false,
        "properties": {
          "proxy_id": {
            "description": "Uno de los proxies; null, directa.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "proxy_id"
        ],
        "type": "object"
      },
      "CuerpoReaccionCanal": {
        "additionalProperties": false,
        "properties": {
          "emoji": {
            "description": "Vacío: quitar la reacción.",
            "maxLength": 32,
            "type": "string"
          },
          "server_id": {
            "description": "El ID de servidor de la publicación (no su ID de mensaje).",
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          }
        },
        "required": [
          "server_id",
          "emoji"
        ],
        "type": "object"
      },
      "CuerpoRecado": {
        "additionalProperties": false,
        "properties": {
          "texto": {
            "description": "Vacío lo deja en blanco. Hasta 50 caracteres (como WhatsApp Web); 139 solo con la forma clasico de Ajustes (perfil.forma_info), que los teléfonos ya no muestran.",
            "maxLength": 139,
            "type": "string"
          }
        },
        "required": [
          "texto"
        ],
        "type": "object"
      },
      "CuerpoReplay": {
        "additionalProperties": false,
        "properties": {
          "desde_seq": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          },
          "event_ids": {
            "items": {
              "type": "string"
            },
            "maxItems": 500,
            "type": [
              "array",
              "null"
            ]
          },
          "hasta_seq": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          },
          "instancia_id": {
            "description": "Con un rango de seq, la instancia.",
            "type": "string"
          },
          "motivo": {
            "description": "Por qué (queda en la auditoría).",
            "maxLength": 300,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "motivo"
        ],
        "type": "object"
      },
      "CuerpoResync": {
        "additionalProperties": false,
        "properties": {
          "colecciones": {
            "description": "regular (etiquetas), regular_low (fijar, archivar, leído) y regular_high (silenciar, destacar, borrar). Vacío: las tres.",
            "items": {
              "type": "string"
            },
            "maxItems": 3,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "type": "object"
      },
      "CuerpoRevocar": {
        "additionalProperties": false,
        "properties": {
          "revocar": {
            "description": "true: el enlace vigente deja de servir y WhatsApp da uno nuevo.",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "CuerpoSilenciarCanal": {
        "additionalProperties": false,
        "properties": {
          "silenciar": {
            "description": "true: silenciarlo; false: reactivar las notificaciones.",
            "type": "boolean"
          }
        },
        "required": [
          "silenciar"
        ],
        "type": "object"
      },
      "CuerpoSolicitudes": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "enum": [
              "approve",
              "reject"
            ],
            "type": "string"
          },
          "participantes": {
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 50,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "accion",
          "participantes"
        ],
        "type": "object"
      },
      "CuerpoSuscripcion": {
        "additionalProperties": false,
        "properties": {
          "instancias": {
            "description": "Vacío: todas las instancias de la app (una key restringida tiene que nombrarlas).",
            "items": {
              "type": "string"
            },
            "maxItems": 200,
            "type": [
              "array",
              "null"
            ]
          },
          "nombre": {
            "examples": [
              "CRM producción"
            ],
            "maxLength": 120,
            "minLength": 1,
            "type": "string"
          },
          "ordenado": {
            "description": "Por omisión, sí: los eventos de una instancia salen en orden de seq.",
            "type": "boolean"
          },
          "tipos": {
            "description": "Vacío: todos los tipos.",
            "examples": [
              [
                "message.received",
                "receipt"
              ]
            ],
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "type": [
              "array",
              "null"
            ]
          },
          "url": {
            "examples": [
              "https://crm.ejemplo.com/webhooks/motor"
            ],
            "maxLength": 2000,
            "minLength": 8,
            "type": "string"
          }
        },
        "required": [
          "nombre",
          "url"
        ],
        "type": "object"
      },
      "CuerpoSuscripcionPresencia": {
        "additionalProperties": false,
        "properties": {
          "destino": {
            "$ref": "#/components/schemas/Destino"
          },
          "ttl_seg": {
            "default": 3600,
            "description": "Cuánto se sigue su presencia (después caduca sola).",
            "format": "int64",
            "maximum": 86400,
            "minimum": 60,
            "type": "integer"
          }
        },
        "required": [
          "destino"
        ],
        "type": "object"
      },
      "CuerpoVerCanal": {
        "additionalProperties": false,
        "properties": {
          "server_ids": {
            "description": "Los ID de servidor de las publicaciones (no los ID de mensaje).",
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "maxItems": 100,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "server_ids"
        ],
        "type": "object"
      },
      "CuerpoVinculo": {
        "additionalProperties": false,
        "properties": {
          "grupo": {
            "$ref": "#/components/schemas/GrupoRef"
          },
          "vincular": {
            "description": "true: vincular el grupo; false: desvincularlo.",
            "type": "boolean"
          }
        },
        "required": [
          "grupo",
          "vincular"
        ],
        "type": "object"
      },
      "Cuota": {
        "additionalProperties": false,
        "properties": {
          "cuota": {
            "description": "Consultas por día de la app (la suya o la de Ajustes).",
            "format": "int64",
            "type": "integer"
          },
          "desglose": {
            "description": "Solo en la consulta de la cuota: lo usado hoy por la app, en todas sus instancias, por tipo de consulta (según la auditoría; una consulta en curso todavía no figura).",
            "items": {
              "$ref": "#/components/schemas/UsoConsultas"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "maximo_por_consulta": {
            "format": "int64",
            "type": "integer"
          },
          "renueva": {
            "description": "Cuándo vuelve a cero (00:00 UTC).",
            "format": "date-time",
            "type": "string"
          },
          "usadas": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "cuota",
          "usadas",
          "renueva",
          "maximo_por_consulta"
        ],
        "type": "object"
      },
      "CuotaComercio": {
        "additionalProperties": false,
        "properties": {
          "cuota": {
            "description": "Consultas comerciales por día de la app (Ajustes). Es aparte de la cuota de identidad (contactos, foto y perfil comercial).",
            "format": "int64",
            "type": "integer"
          },
          "desglose": {
            "description": "Lo usado hoy por la app, en todas sus instancias, por tipo de consulta (según la auditoría, también las que fallaron; una consulta en curso todavía no figura).",
            "items": {
              "$ref": "#/components/schemas/UsoComercio"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "renueva": {
            "description": "Cuándo vuelve a cero (00:00 UTC).",
            "format": "date-time",
            "type": "string"
          },
          "usadas": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "cuota",
          "usadas",
          "renueva"
        ],
        "type": "object"
      },
      "DatoPerfil": {
        "additionalProperties": false,
        "properties": {
          "confirmado": {
            "description": "Un evento de WhatsApp o una consulta dijeron lo mismo.",
            "type": "boolean"
          },
          "desde": {
            "description": "Quién lo fijó: el teléfono (whatsapp), un comando (motor) o una consulta.",
            "enum": [
              "whatsapp",
              "motor",
              "consulta",
              ""
            ],
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "valor": {
            "type": "string"
          }
        },
        "required": [
          "valor",
          "confirmado"
        ],
        "type": "object"
      },
      "DatosAppState": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "enum": [
              "fijar",
              "desfijar",
              "archivar",
              "desarchivar",
              "silenciar",
              "reactivar",
              "marcar_leido",
              "marcar_no_leido",
              "destacar",
              "quitar_destacado",
              "borrar_chat",
              "poner_candado",
              "quitar_candado"
            ],
            "type": "string"
          },
          "borrar_medios": {
            "type": "boolean"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "coleccion": {
            "enum": [
              "regular",
              "regular_low",
              "regular_high"
            ],
            "type": "string"
          },
          "desde": {
            "description": "whatsapp: el teléfono u otro dispositivo; motor: un comando (con su command_id).",
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          },
          "estado": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EstadoChat"
              }
            ],
            "description": "El estado del chat después del cambio."
          },
          "full_sync": {
            "description": "Llegó en una sincronización completa (el estado ya existía).",
            "type": "boolean"
          },
          "mensaje": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MensajeVista"
              }
            ],
            "description": "destacar y quitar_destacado: el mensaje."
          },
          "momento": {
            "description": "El momento del cambio en el appstate de WhatsApp.",
            "format": "date-time",
            "type": "string"
          },
          "silenciado_hasta": {
            "format": "date-time",
            "type": "string"
          },
          "version": {
            "description": "La versión de la colección cuando el motor aplicó el cambio.",
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "accion",
          "chat",
          "momento",
          "coleccion",
          "version",
          "full_sync",
          "desde"
        ],
        "type": "object"
      },
      "DatosAsociacion": {
        "additionalProperties": false,
        "properties": {
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          },
          "etiqueta": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EtiquetaRef"
              }
            ],
            "description": "Vacío si el motor todavía no conoce la etiqueta."
          },
          "full_sync": {
            "type": "boolean"
          },
          "label_id": {
            "type": "string"
          },
          "mensaje": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MensajeVista"
              }
            ],
            "description": "Si la etiqueta es de un mensaje (no del chat)."
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "version": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "label_id",
          "chat",
          "momento",
          "version",
          "full_sync",
          "desde"
        ],
        "type": "object"
      },
      "DatosBloqueos": {
        "additionalProperties": false,
        "properties": {
          "cambios": {
            "items": {
              "$ref": "#/components/schemas/BloqueoVista"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          }
        },
        "required": [
          "cambios",
          "desde"
        ],
        "type": "object"
      },
      "DatosContacto": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "description": "campo libreta: guardado (no estaba en la libreta), renombrado (otro nombre) o borrado (lo quitaron de la libreta; contacto.nombre queda vacío).",
            "enum": [
              "guardado",
              "renombrado",
              "borrado"
            ],
            "type": "string"
          },
          "campo": {
            "enum": [
              "libreta",
              "push_name",
              "negocio",
              "foto",
              "recado"
            ],
            "type": "string"
          },
          "contacto": {
            "$ref": "#/components/schemas/ContactoVista"
          },
          "full_sync": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "origen": {
            "description": "whatsapp: lo informó WhatsApp; consulta: lo trajo una consulta de perfil.",
            "enum": [
              "whatsapp",
              "consulta"
            ],
            "type": "string"
          }
        },
        "required": [
          "contacto",
          "campo",
          "momento",
          "origen"
        ],
        "type": "object"
      },
      "DatosEnviado": {
        "additionalProperties": false,
        "properties": {
          "aceptado_en": {
            "description": "Cuándo lo aceptó el servidor de WhatsApp (no es entregado ni leído).",
            "format": "date-time",
            "type": "string"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "command_id": {
            "type": "string"
          },
          "conciliado": {
            "type": "boolean"
          },
          "objetivo": {
            "type": "string"
          },
          "operacion": {
            "enum": [
              "edicion",
              "revocacion",
              "reaccion",
              ""
            ],
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "server_id": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "chat",
          "provider_id",
          "command_id",
          "aceptado_en"
        ],
        "type": "object"
      },
      "DatosEtiqueta": {
        "additionalProperties": false,
        "properties": {
          "anterior": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EtiquetaRef"
              }
            ],
            "description": "label.updated: el nombre y el color de antes."
          },
          "coleccion": {
            "type": "string"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          },
          "etiqueta": {
            "$ref": "#/components/schemas/EtiquetaVista"
          },
          "full_sync": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "version": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "etiqueta",
          "momento",
          "version",
          "full_sync",
          "desde",
          "coleccion"
        ],
        "type": "object"
      },
      "DatosEvento": {
        "additionalProperties": false,
        "properties": {
          "bytes": {
            "format": "int64",
            "type": "integer"
          },
          "command_id": {
            "description": "El envío que lo usa (si se importó de una URL).",
            "type": "string"
          },
          "estado": {
            "enum": [
              "listo",
              "fallido"
            ],
            "type": "string"
          },
          "media_id": {
            "type": "string"
          },
          "mime": {
            "type": "string"
          },
          "motivo": {
            "description": "Por qué falló: vencido_en_whatsapp, invalido, demasiado_grande, cuota_excedida, reintentos_agotados, url_no_permitida, url_rechazada…",
            "type": "string"
          },
          "origen": {
            "enum": [
              "entrante",
              "url",
              "conversion"
            ],
            "type": "string"
          },
          "provider_id": {
            "description": "El mensaje que trajo el medio (si es entrante).",
            "type": "string"
          },
          "sha256": {
            "type": "string"
          }
        },
        "required": [
          "media_id",
          "origen",
          "estado"
        ],
        "type": "object"
      },
      "DatosIndescifrable": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "es_grupo": {
            "type": "boolean"
          },
          "from_me": {
            "type": "boolean"
          },
          "modo_fallo": {
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "no_disponible": {
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          },
          "tipo_no_disponible": {
            "type": "string"
          }
        },
        "required": [
          "chat",
          "provider_id",
          "from_me",
          "es_grupo",
          "no_disponible",
          "momento"
        ],
        "type": "object"
      },
      "DatosLlamada": {
        "additionalProperties": false,
        "properties": {
          "call_id": {
            "type": "string"
          },
          "de": {
            "$ref": "#/components/schemas/Peer"
          },
          "elementos": {
            "description": "call.offer: los nombres de los elementos de la oferta (audio, video, net…), sin sus datos. Diagnóstico: video sale de un elemento video.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo": {
            "description": "call.terminate: el motivo que informa WhatsApp (código).",
            "type": "string"
          },
          "rechazo": {
            "description": "call.rejected: quién la rechazó desde el motor.",
            "enum": [
              "automatico",
              "operador",
              "app",
              ""
            ],
            "type": "string"
          },
          "video": {
            "type": "boolean"
          }
        },
        "required": [
          "call_id",
          "de",
          "video",
          "momento"
        ],
        "type": "object"
      },
      "DatosNota": {
        "additionalProperties": false,
        "properties": {
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "coleccion": {
            "enum": [
              "regular",
              "regular_low",
              "regular_high"
            ],
            "type": "string"
          },
          "desde": {
            "description": "Siempre whatsapp: el motor no escribe notas.",
            "enum": [
              "whatsapp"
            ],
            "type": "string"
          },
          "full_sync": {
            "type": "boolean"
          },
          "momento": {
            "description": "El momento del cambio en el appstate de WhatsApp.",
            "format": "date-time",
            "type": "string"
          },
          "nota": {
            "$ref": "#/components/schemas/NotaVista"
          },
          "version": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "chat",
          "nota",
          "momento",
          "coleccion",
          "version",
          "full_sync",
          "desde"
        ],
        "type": "object"
      },
      "DatosPeerUnido": {
        "additionalProperties": false,
        "properties": {
          "peer": {
            "$ref": "#/components/schemas/Peer"
          },
          "unidos": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "peer",
          "unidos"
        ],
        "type": "object"
      },
      "DatosPerfil": {
        "additionalProperties": false,
        "properties": {
          "campo": {
            "enum": [
              "nombre",
              "recado",
              "foto"
            ],
            "type": "string"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "quitada": {
            "description": "foto: se quitó.",
            "type": "boolean"
          },
          "valor": {
            "description": "El nombre, el recado o el ID de la foto.",
            "type": "string"
          }
        },
        "required": [
          "campo",
          "desde",
          "momento"
        ],
        "type": "object"
      },
      "DatosPresencia": {
        "additionalProperties": false,
        "properties": {
          "chat": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Si es lo que hace en un chat (escribiendo, grabando)."
          },
          "de": {
            "$ref": "#/components/schemas/Peer"
          },
          "disponible": {
            "type": "boolean"
          },
          "estado_chat": {
            "enum": [
              "escribiendo",
              "grabando",
              "pausado",
              ""
            ],
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "ultima_vez": {
            "description": "Solo si el contacto la comparte (privacidad).",
            "format": "date-time",
            "type": "string"
          },
          "vence_en": {
            "description": "Hasta cuándo se sigue su presencia (TTL de la suscripción).",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "de",
          "momento",
          "vence_en"
        ],
        "type": "object"
      },
      "DatosPrivacidad": {
        "additionalProperties": false,
        "properties": {
          "cambiadas": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          },
          "privacidad": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "temporizador_por_defecto_seg": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "privacidad",
          "cambiadas",
          "desde"
        ],
        "type": "object"
      },
      "DatosRecibo": {
        "additionalProperties": false,
        "properties": {
          "aplicados": {
            "format": "int64",
            "type": "integer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "es_grupo": {
            "type": "boolean"
          },
          "from_me": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "pendientes": {
            "format": "int64",
            "type": "integer"
          },
          "provider_ids": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "remitente": {
            "$ref": "#/components/schemas/Peer"
          },
          "tipo": {
            "type": "string"
          },
          "tipo_proveedor": {
            "type": "string"
          }
        },
        "required": [
          "chat",
          "from_me",
          "es_grupo",
          "provider_ids",
          "tipo",
          "momento",
          "aplicados",
          "pendientes"
        ],
        "type": "object"
      },
      "DatosRespuesta": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "$ref": "#/components/schemas/AccionRespondida"
          },
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "correlacion": {
            "enum": [
              "correlacionada",
              "accion_desconocida",
              "sin_mensaje",
              "otro_chat",
              "otro_autor",
              "no_respondible",
              "desconocida"
            ],
            "type": "string"
          },
          "crudo": {
            "description": "interactive.unknown: lo que llegó, saneado y acotado (sin el mensaje citado)."
          },
          "formato": {
            "description": "texto: el número de una opción del respaldo de una lista (respaldo_texto).",
            "enum": [
              "buttons_response",
              "list_response",
              "template_button_reply",
              "native_flow",
              "texto",
              "desconocida"
            ],
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "mensaje": {
            "$ref": "#/components/schemas/RefMensajeInteractivo"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo": {
            "description": "interactive.unknown: formato_desconocido, flujo_desconocido, sin_id, id_invalido, contexto_invalido o parametros_invalidos.",
            "type": "string"
          },
          "nombre_flujo": {
            "type": "string"
          },
          "parametros": {
            "additionalProperties": {},
            "description": "Los de una respuesta de native flow: un objeto JSON acotado y saneado.",
            "type": "object"
          },
          "provider_id": {
            "type": "string"
          },
          "via": {
            "description": "texto: la fila se eligió contestando su número al respaldo de texto de la lista (no por la lista).",
            "enum": [
              "texto",
              ""
            ],
            "type": "string"
          }
        },
        "required": [
          "chat",
          "autor",
          "provider_id",
          "from_me",
          "formato",
          "accion",
          "correlacion",
          "momento"
        ],
        "type": "object"
      },
      "DatosRespuestaRevisada": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "$ref": "#/components/schemas/AccionRespondida"
          },
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "correlacion": {
            "enum": [
              "correlacionada",
              "accion_desconocida",
              "sin_mensaje",
              "otro_chat",
              "otro_autor",
              "no_respondible",
              "desconocida"
            ],
            "type": "string"
          },
          "correlacion_anterior": {
            "enum": [
              "otro_chat",
              "otro_autor"
            ],
            "type": "string"
          },
          "crudo": {
            "description": "interactive.unknown: lo que llegó, saneado y acotado (sin el mensaje citado)."
          },
          "formato": {
            "description": "texto: el número de una opción del respaldo de una lista (respaldo_texto).",
            "enum": [
              "buttons_response",
              "list_response",
              "template_button_reply",
              "native_flow",
              "texto",
              "desconocida"
            ],
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "mensaje": {
            "$ref": "#/components/schemas/RefMensajeInteractivo"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo": {
            "description": "interactive.unknown: formato_desconocido, flujo_desconocido, sin_id, id_invalido, contexto_invalido o parametros_invalidos.",
            "type": "string"
          },
          "nombre_flujo": {
            "type": "string"
          },
          "parametros": {
            "additionalProperties": {},
            "description": "Los de una respuesta de native flow: un objeto JSON acotado y saneado.",
            "type": "object"
          },
          "provider_id": {
            "type": "string"
          },
          "response_event_id": {
            "description": "El event_id del interactive.response original: la identidad estable de la respuesta.",
            "type": "string"
          },
          "response_id": {
            "type": "string"
          },
          "via": {
            "description": "texto: la fila se eligió contestando su número al respaldo de texto de la lista (no por la lista).",
            "enum": [
              "texto",
              ""
            ],
            "type": "string"
          }
        },
        "required": [
          "response_id",
          "response_event_id",
          "correlacion_anterior",
          "chat",
          "autor",
          "provider_id",
          "from_me",
          "formato",
          "accion",
          "correlacion",
          "momento"
        ],
        "type": "object"
      },
      "DatosSync": {
        "additionalProperties": false,
        "properties": {
          "coleccion": {
            "enum": [
              "regular",
              "regular_low",
              "regular_high"
            ],
            "type": "string"
          },
          "error": {
            "description": "Código acotado: clave_faltante, mac_invalido, tiempo_excedido, sin_sesion, rechazado, no_capturado, otro.",
            "type": "string"
          },
          "estado": {
            "enum": [
              "al_dia",
              "error",
              "clave_faltante"
            ],
            "type": "string"
          },
          "full_sync": {
            "type": "boolean"
          },
          "recuperacion": {
            "description": "La copia que mandó el teléfono a pedido del motor (una clave que no llegaba).",
            "type": "boolean"
          },
          "reintentos": {
            "format": "int64",
            "type": "integer"
          },
          "version": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "coleccion",
          "estado",
          "version",
          "full_sync",
          "recuperacion"
        ],
        "type": "object"
      },
      "DatosTemporizador": {
        "additionalProperties": false,
        "properties": {
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "es_grupo": {
            "type": "boolean"
          },
          "from_me": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "segundos": {
            "description": "0: desactivado; 86400 (24 h), 604800 (7 días) o 7776000 (90 días).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "chat",
          "from_me",
          "es_grupo",
          "segundos",
          "momento"
        ],
        "type": "object"
      },
      "DatosVencido": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "from_me": {
            "type": "boolean"
          },
          "message_ref": {
            "description": "La referencia del mensaje en el store (GET /v1/instances/{id}/messages/{message_ref}).",
            "type": "string"
          },
          "momento": {
            "description": "Cuándo se mandó el mensaje.",
            "format": "date-time",
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "vence_en": {
            "description": "El momento más su expiracion_seg: cuándo venció.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "chat",
          "provider_id",
          "from_me",
          "message_ref",
          "momento",
          "vence_en"
        ],
        "type": "object"
      },
      "DatosVoto": {
        "additionalProperties": false,
        "properties": {
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "descifrado": {
            "type": "boolean"
          },
          "encuesta": {
            "description": "El provider_id de la encuesta.",
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "opciones": {
            "description": "Lo que eligió ahora (vacío: quitó su voto); reemplaza su voto anterior.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "provider_id": {
            "type": "string"
          },
          "resultado": {
            "$ref": "#/components/schemas/ResultadoEncuesta"
          },
          "vigente": {
            "description": "false: llegó un voto más viejo que el que ya estaba (no cambia el resultado).",
            "type": "boolean"
          },
          "votante": {
            "$ref": "#/components/schemas/Peer"
          }
        },
        "required": [
          "chat",
          "votante",
          "provider_id",
          "encuesta",
          "from_me",
          "descifrado",
          "opciones",
          "vigente",
          "momento",
          "resultado"
        ],
        "type": "object"
      },
      "Destino": {
        "additionalProperties": false,
        "properties": {
          "jid": {
            "description": "JID del chat: usuario (@s.whatsapp.net o @lid) o grupo (@g.us).",
            "maxLength": 128,
            "type": "string"
          },
          "peer_ref": {
            "description": "El peer_ref de un evento de esta instancia.",
            "type": "string"
          },
          "telefono": {
            "description": "Número internacional (chat directo).",
            "examples": [
              "+NUMERO_DEL_CONTACTO"
            ],
            "maxLength": 32,
            "type": "string"
          }
        },
        "type": "object"
      },
      "Diagnostico": {
        "additionalProperties": false,
        "properties": {
          "alertas": {
            "description": "Abiertas.",
            "items": {
              "$ref": "#/components/schemas/Alerta"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "caida_desde": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "checked_at": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "estado": {
            "type": "string"
          },
          "estado_deseado": {
            "type": "string"
          },
          "instancia_id": {
            "type": "string"
          },
          "keepalive": {
            "$ref": "#/components/schemas/KeepAlive"
          },
          "motivo": {
            "type": "string"
          },
          "multimedia": {
            "$ref": "#/components/schemas/MultimediaDiag"
          },
          "pendiente": {
            "$ref": "#/components/schemas/Pendiente"
          },
          "pool": {
            "$ref": "#/components/schemas/Pool"
          },
          "proceso": {
            "$ref": "#/components/schemas/Proceso"
          },
          "reconexiones": {
            "$ref": "#/components/schemas/Reconexiones"
          },
          "sesion": {
            "$ref": "#/components/schemas/SesionViva"
          },
          "ultimo_error": {
            "$ref": "#/components/schemas/ErrorDiag"
          },
          "ultimo_evento": {
            "$ref": "#/components/schemas/UltimoEvento"
          }
        },
        "required": [
          "instancia_id",
          "estado",
          "estado_deseado",
          "motivo",
          "checked_at",
          "caida_desde",
          "sesion",
          "ultimo_evento",
          "pendiente",
          "ultimo_error",
          "reconexiones",
          "keepalive",
          "pool",
          "multimedia",
          "alertas",
          "proceso"
        ],
        "type": "object"
      },
      "Emparejamiento": {
        "additionalProperties": false,
        "properties": {
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "fase": {
            "type": "string"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "modo": {
            "enum": [
              "qr",
              "codigo"
            ],
            "type": "string"
          },
          "reto": {
            "$ref": "#/components/schemas/RetoVista"
          },
          "terminado_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "generacion",
          "modo",
          "fase",
          "reto",
          "creado_en",
          "terminado_en"
        ],
        "type": "object"
      },
      "EnVivoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "en_vivo_hasta": {
            "description": "Hasta cuándo llegan las vistas y reacciones en vivo (newsletter.updates).",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "en_vivo_hasta"
        ],
        "type": "object"
      },
      "Encuesta": {
        "additionalProperties": false,
        "properties": {
          "opciones": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pregunta": {
            "type": "string"
          },
          "seleccionables": {
            "description": "1: una sola opción; 0: varias.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "pregunta",
          "opciones",
          "seleccionables"
        ],
        "type": "object"
      },
      "Envelope": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "data": {},
          "event_id": {
            "type": "string"
          },
          "generation": {
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "type": "string"
          },
          "occurred_at": {
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "ErrorDetail": {
        "additionalProperties": false,
        "properties": {
          "location": {
            "description": "Where the error occurred, e.g. 'body.items[3].tags' or 'path.thing-id'",
            "type": "string"
          },
          "message": {
            "description": "Error message text",
            "type": "string"
          },
          "value": {
            "description": "The value at the given location"
          }
        },
        "type": "object"
      },
      "ErrorDiag": {
        "additionalProperties": false,
        "properties": {
          "codigo": {
            "type": "string"
          },
          "en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "codigo",
          "en"
        ],
        "type": "object"
      },
      "ErrorModel": {
        "additionalProperties": false,
        "properties": {
          "detail": {
            "description": "A human-readable explanation specific to this occurrence of the problem.",
            "examples": [
              "Property foo is required but is missing."
            ],
            "type": "string"
          },
          "errors": {
            "description": "Optional list of individual error details",
            "items": {
              "$ref": "#/components/schemas/ErrorDetail"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "instance": {
            "description": "A URI reference that identifies the specific occurrence of the problem.",
            "examples": [
              "https://example.com/error-log/abc123"
            ],
            "format": "uri",
            "type": "string"
          },
          "status": {
            "description": "HTTP status code",
            "examples": [
              400
            ],
            "format": "int64",
            "type": "integer"
          },
          "title": {
            "description": "A short, human-readable summary of the problem type. This value should not change between occurrences of the error.",
            "examples": [
              "Bad Request"
            ],
            "type": "string"
          },
          "type": {
            "default": "about:blank",
            "description": "A URI reference to human-readable documentation for the error.",
            "examples": [
              "https://example.com/errors/example"
            ],
            "format": "uri",
            "type": "string"
          }
        },
        "type": "object"
      },
      "EstadoChat": {
        "additionalProperties": false,
        "properties": {
          "actividad_en": {
            "format": "date-time",
            "type": "string"
          },
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "archivado": {
            "description": "Archivado en WhatsApp. NO es «conversación resuelta» del CRM: el CRM lleva sus estados propios.",
            "type": "boolean"
          },
          "borrado": {
            "description": "Se borró del estado de WhatsApp y no llegó un mensaje más nuevo. El ledger y las entregas del motor no se tocan.",
            "type": "boolean"
          },
          "borrado_en": {
            "format": "date-time",
            "type": "string"
          },
          "candado": {
            "description": "El chat tiene candado en WhatsApp (el teléfono lo muestra en «Chats bloqueados»).",
            "type": "boolean"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "etiquetas": {
            "items": {
              "$ref": "#/components/schemas/EtiquetaRef"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "fijado": {
            "type": "boolean"
          },
          "no_leido": {
            "description": "La marca manual «no leído» de WhatsApp (no es el contador de mensajes sin leer).",
            "type": "boolean"
          },
          "silenciado": {
            "type": "boolean"
          },
          "silenciado_hasta": {
            "description": "Hasta cuándo (vacío con silenciado: para siempre).",
            "format": "date-time",
            "type": "string"
          },
          "ultimo_mensaje_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "chat",
          "fijado",
          "archivado",
          "silenciado",
          "no_leido",
          "borrado",
          "candado",
          "etiquetas",
          "actividad_en",
          "actualizado_en"
        ],
        "type": "object"
      },
      "EstadoHistorial": {
        "additionalProperties": false,
        "properties": {
          "aviso": {
            "type": "string"
          },
          "has_more": {
            "type": "boolean"
          },
          "lotes": {
            "$ref": "#/components/schemas/ResumenLotes"
          },
          "next_cursor": {
            "description": "El cursor de la página siguiente (los más viejos).",
            "type": "string"
          },
          "politica": {
            "$ref": "#/components/schemas/PoliticaHistorial"
          },
          "trabajos": {
            "items": {
              "$ref": "#/components/schemas/TrabajoSync"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "politica",
          "trabajos",
          "has_more",
          "lotes",
          "aviso"
        ],
        "type": "object"
      },
      "EstadoWA": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "command_id": {
            "description": "El comando del motor que lo publicó.",
            "type": "string"
          },
          "direccion": {
            "enum": [
              "entrante",
              "saliente"
            ],
            "type": "string"
          },
          "mime": {
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "retener_hasta": {
            "description": "Hasta cuándo lo guarda el motor (después se borra y su evento queda redactado).",
            "format": "date-time",
            "type": "string"
          },
          "revocado": {
            "description": "Quien lo publicó lo borró: ya no tiene contenido.",
            "type": "boolean"
          },
          "status_id": {
            "type": "string"
          },
          "texto": {
            "description": "El texto o el caption.",
            "type": "string"
          },
          "tipo": {
            "type": "string"
          },
          "vence_en": {
            "description": "Cuándo vence en WhatsApp (24 horas).",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status_id",
          "provider_id",
          "direccion",
          "tipo",
          "momento",
          "vence_en",
          "retener_hasta",
          "revocado"
        ],
        "type": "object"
      },
      "EstadosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "estados": {
            "items": {
              "$ref": "#/components/schemas/EstadoWA"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "estados",
          "has_more"
        ],
        "type": "object"
      },
      "EtiquetaRef": {
        "additionalProperties": false,
        "properties": {
          "color": {
            "description": "El índice de la paleta de WhatsApp (0 a 19).",
            "format": "int64",
            "type": "integer"
          },
          "label_id": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          }
        },
        "required": [
          "label_id",
          "nombre",
          "color"
        ],
        "type": "object"
      },
      "EtiquetaVista": {
        "additionalProperties": false,
        "properties": {
          "actualizada_en": {
            "format": "date-time",
            "type": "string"
          },
          "cambio_en": {
            "format": "date-time",
            "type": "string"
          },
          "chats": {
            "description": "Cuántos chats la tienen puesta.",
            "format": "int64",
            "type": "integer"
          },
          "color": {
            "description": "El índice de la paleta de WhatsApp (0 a 19).",
            "format": "int64",
            "type": "integer"
          },
          "eliminada": {
            "type": "boolean"
          },
          "label_id": {
            "type": "string"
          },
          "mensajes": {
            "description": "Cuántos mensajes la tienen puesta.",
            "format": "int64",
            "type": "integer"
          },
          "nombre": {
            "type": "string"
          },
          "orden": {
            "format": "int64",
            "type": "integer"
          },
          "predefinida": {
            "description": "El ID de una etiqueta predefinida de WhatsApp Business.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "label_id",
          "nombre",
          "color",
          "eliminada",
          "chats",
          "mensajes",
          "actualizada_en"
        ],
        "type": "object"
      },
      "EtiquetasOutputBody": {
        "additionalProperties": false,
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "labels": {
            "items": {
              "$ref": "#/components/schemas/EtiquetaVista"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "labels",
          "has_more"
        ],
        "type": "object"
      },
      "EvCamposCanal": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "type": "string"
          },
          "estado": {
            "description": "active, suspended o geosuspended (lo que dice WhatsApp).",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "rol": {
            "enum": [
              "owner",
              "admin",
              "subscriber",
              "guest"
            ],
            "type": "string"
          },
          "siguiendo": {
            "type": "boolean"
          },
          "silenciado": {
            "type": "boolean"
          },
          "verificado": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "EvCamposGrupo": {
        "additionalProperties": false,
        "properties": {
          "anuncio": {
            "description": "Solo los administradores escriben.",
            "type": "boolean"
          },
          "aprobacion": {
            "description": "Entrar exige la aprobación de un administrador.",
            "type": "boolean"
          },
          "bloqueado": {
            "description": "Solo los administradores editan la información.",
            "type": "boolean"
          },
          "comunidad": {
            "description": "El peer_ref de su comunidad (null: ya no tiene).",
            "type": [
              "string",
              "null"
            ]
          },
          "descripcion": {
            "type": "string"
          },
          "efimero_seg": {
            "format": "int64",
            "type": "integer"
          },
          "eliminado": {
            "description": "Siempre true: el grupo se eliminó.",
            "type": "boolean"
          },
          "es_comunidad": {
            "type": "boolean"
          },
          "foto_id": {
            "description": "El ID de la foto nueva (vacío: la quitaron).",
            "type": "string"
          },
          "invitacion": {
            "description": "Siempre true: cambió el enlace de invitación (el enlace no viaja).",
            "type": "boolean"
          },
          "miembro": {
            "description": "false: el número salió o lo sacaron.",
            "type": "boolean"
          },
          "modo_agregar": {
            "description": "admin_add o all_member_add.",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "rol_propio": {
            "enum": [
              "miembro",
              "admin",
              "superadmin"
            ],
            "type": "string"
          },
          "suspendido": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "EvCita": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "description": "El JID de quien escribió el citado, si se conoce.",
            "type": "string"
          },
          "citado_vencido": {
            "description": "El citado era un mensaje temporal y venció: de la cita queda solo su provider_id.",
            "type": "boolean"
          },
          "de_mi": {
            "description": "El citado es propio. Falta cuando citado_vencido.",
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          }
        },
        "required": [
          "provider_id"
        ],
        "type": "object"
      },
      "EvContacto": {
        "additionalProperties": false,
        "properties": {
          "nombre": {
            "type": "string"
          },
          "telefonos": {
            "description": "Los teléfonos de la vCard.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "vcard": {
            "type": "string"
          }
        },
        "required": [
          "nombre",
          "vcard"
        ],
        "type": "object"
      },
      "EvContenido": {
        "additionalProperties": false,
        "properties": {
          "cita": {
            "$ref": "#/components/schemas/EvCita"
          },
          "contactos": {
            "items": {
              "$ref": "#/components/schemas/EvContacto"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "encuesta": {
            "$ref": "#/components/schemas/Encuesta"
          },
          "expiracion_seg": {
            "description": "El mensaje es temporal: vence a los N segundos de su momento. WhatsApp no avisa el vencimiento; el motor borra su contenido y sus medios y emite message.expired.",
            "format": "int64",
            "type": "integer"
          },
          "medio": {
            "$ref": "#/components/schemas/EvMedio"
          },
          "menciones": {
            "description": "Los JID mencionados.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "no_soportado": {
            "description": "El tipo del proveedor que el motor no modela.",
            "type": "string"
          },
          "reenviado": {
            "type": "boolean"
          },
          "texto": {
            "description": "El texto o el caption.",
            "type": "string"
          },
          "tipo": {
            "description": "texto, imagen, video, audio, documento, sticker, ubicacion, ubicacion_en_vivo, contactos, encuesta o no_soportado.",
            "type": "string"
          },
          "ubicacion": {
            "$ref": "#/components/schemas/EvUbicacion"
          },
          "vista_previa": {
            "$ref": "#/components/schemas/EvVistaPrevia"
          }
        },
        "required": [
          "tipo"
        ],
        "type": "object"
      },
      "EvDatosBaneo": {
        "additionalProperties": false,
        "properties": {
          "codigo": {
            "description": "El código del bloqueo que informó WhatsApp.",
            "format": "int64",
            "type": "integer"
          },
          "expira_en": {
            "description": "Cuándo termina el bloqueo, si WhatsApp lo dijo.",
            "format": "date-time",
            "type": "string"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "codigo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosCambioEstado": {
        "additionalProperties": false,
        "properties": {
          "a": {
            "enum": [
              "nuevo",
              "esperando_qr",
              "esperando_codigo",
              "accion_requerida",
              "emparejando",
              "emparejado",
              "conectado",
              "desconectado",
              "reconectando",
              "intento_vencido",
              "error",
              "cerrado_por_telefono",
              "cerrado_por_operador",
              "reemplazado",
              "bloqueado",
              "archivado"
            ],
            "type": "string"
          },
          "de": {
            "description": "El estado anterior (null al crear la instancia).",
            "type": [
              "string",
              "null"
            ]
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "description": "El motivo tipificado del estado nuevo (socket, keepalive, operador, pausada, qr_vencido, logged_out, baneo_temporal…); vacío si no hay.",
            "type": "string"
          }
        },
        "required": [
          "de",
          "a",
          "motivo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosCanalCambio": {
        "additionalProperties": false,
        "properties": {
          "campos": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvCamposCanal"
              }
            ],
            "description": "Solo los campos que cambiaron, con su valor nuevo."
          },
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          }
        },
        "required": [
          "canal",
          "campos",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosCanalContadores": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "publicaciones": {
            "description": "Solo las publicaciones cuyas vistas o reacciones cambiaron.",
            "items": {
              "$ref": "#/components/schemas/ContadorVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "canal",
          "publicaciones",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosCanalSalida": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "rol": {
            "description": "El rol que informó el aviso (suele venir vacío).",
            "type": "string"
          }
        },
        "required": [
          "canal",
          "rol",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosCanalSilencio": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "silenciado": {
            "type": "boolean"
          }
        },
        "required": [
          "canal",
          "silenciado",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosCanalUnido": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "rol": {
            "enum": [
              "owner",
              "admin",
              "subscriber",
              "guest"
            ],
            "type": "string"
          }
        },
        "required": [
          "canal",
          "nombre",
          "rol",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosComandoAceptado": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "type": "string"
          },
          "respaldo_de": {
            "description": "El texto de respaldo de una lista: el command_id de la lista.",
            "type": "string"
          },
          "type": {
            "description": "El tipo del comando (message.text, group.create…).",
            "type": "string"
          }
        },
        "required": [
          "command_id",
          "type"
        ],
        "type": "object"
      },
      "EvDatosComandoCancelado": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "command_id",
          "type"
        ],
        "type": "object"
      },
      "EvDatosComandoFallido": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "type": "string"
          },
          "error_code": {
            "description": "El código del error (el mismo del comando).",
            "type": "string"
          },
          "provider_message_id": {
            "description": "Envíos: el ID fijo del mensaje (puede venir vacío).",
            "type": "string"
          },
          "server_code": {
            "description": "El código numérico que respondió WhatsApp, si lo hubo.",
            "format": "int64",
            "type": "integer"
          },
          "server_origin": {
            "description": "Por dónde llegó server_code (iq, graphql, mex…).",
            "type": "string"
          },
          "stage": {
            "description": "Envíos: en qué etapa quedó (previa: no salió; servidor: lo rechazó WhatsApp; frontera: no se sabe si salió).",
            "enum": [
              "previa",
              "servidor",
              "frontera",
              ""
            ],
            "type": "string"
          },
          "type": {
            "description": "El tipo del comando.",
            "type": "string"
          }
        },
        "required": [
          "command_id",
          "type",
          "error_code"
        ],
        "type": "object"
      },
      "EvDatosComunidadCambio": {
        "additionalProperties": false,
        "properties": {
          "anuncios": {
            "description": "Es el grupo de anuncios de la comunidad.",
            "type": "boolean"
          },
          "comunidad": {
            "$ref": "#/components/schemas/Peer"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "motivo": {
            "description": "otra_comunidad: salió porque pasó a otra comunidad.",
            "enum": [
              "otra_comunidad",
              ""
            ],
            "type": "string"
          },
          "nombre": {
            "description": "El nombre del grupo, si se conoce.",
            "type": "string"
          },
          "version": {
            "description": "Sube con cada cambio del vínculo.",
            "format": "int64",
            "type": "integer"
          },
          "vinculado": {
            "description": "true: el grupo quedó dentro de la comunidad; false: salió.",
            "type": "boolean"
          }
        },
        "required": [
          "comunidad",
          "grupo",
          "vinculado",
          "version",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosConsultaCompletada": {
        "additionalProperties": false,
        "properties": {
          "cantidad": {
            "format": "int64",
            "type": "integer"
          },
          "consulta_id": {
            "type": "string"
          },
          "continuacion": {
            "description": "catalogo: hay otra página.",
            "type": "boolean"
          },
          "operacion": {
            "enum": [
              "catalogo",
              "colecciones"
            ],
            "type": "string"
          },
          "resultado": {
            "enum": [
              "ok"
            ],
            "type": "string"
          },
          "vence_en": {
            "description": "Hasta cuándo sirve su cursor.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "consulta_id",
          "operacion",
          "resultado",
          "cantidad",
          "vence_en"
        ],
        "type": "object"
      },
      "EvDatosConsultaFallida": {
        "additionalProperties": false,
        "properties": {
          "codigo": {
            "description": "El código propio del error (el mismo de la respuesta HTTP).",
            "type": "string"
          },
          "consulta_id": {
            "type": "string"
          },
          "operacion": {
            "enum": [
              "catalogo",
              "colecciones"
            ],
            "type": "string"
          },
          "server_code": {
            "description": "El código numérico que respondió WhatsApp, si lo hubo.",
            "format": "int64",
            "type": "integer"
          },
          "server_origin": {
            "description": "Por dónde llegó server_code (iq, graphql, mex…).",
            "type": "string"
          },
          "via": {
            "description": "La vía de consulta que se pidió.",
            "type": "string"
          }
        },
        "required": [
          "consulta_id",
          "operacion",
          "codigo"
        ],
        "type": "object"
      },
      "EvDatosDesconectado": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "description": "socket (se cayó y el SDK reconecta), keepalive (el motor reinició el socket), operador o pausada (a pedido), apagado, traspaso, sin_sesion o captura_fallida.",
            "type": "string"
          }
        },
        "required": [
          "motivo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosDesconocido": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "protocolo": {
            "description": "ProtocolMessage: el tipo de aviso de protocolo (sin contenido).",
            "type": "string"
          },
          "sdk": {
            "description": "El evento del SDK serializado tal cual (su forma depende de sdk_tipo y de la versión fijada del SDK)."
          },
          "sdk_tipo": {
            "description": "El nombre del evento del SDK (o ProtocolMessage, SecretEncryptedMessage).",
            "type": "string"
          },
          "secreto": {
            "description": "SecretEncryptedMessage: el tipo de mensaje cifrado aparte (sin contenido).",
            "type": "string"
          }
        },
        "required": [
          "sdk_tipo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosEmparejado": {
        "additionalProperties": false,
        "properties": {
          "conciliado": {
            "description": "true: el vínculo se confirmó al arrancar el motor, con el dispositivo ya guardado (el emparejamiento se cortó antes de terminar).",
            "type": "boolean"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "numero": {
            "description": "El número vinculado (solo si el JID es un PN).",
            "type": "string"
          },
          "plataforma": {
            "description": "La plataforma que informó WhatsApp al vincular.",
            "type": "string"
          }
        },
        "required": [
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosEmparejamientoFallido": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "description": "Código acotado: telefono_rechazado, cliente_desactualizado, sin_multidispositivo, estado_inesperado, error_emparejamiento, passkey, vinculo_rechazado, conexion o el de una autorización revocada.",
            "type": "string"
          }
        },
        "required": [
          "motivo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosError": {
        "additionalProperties": false,
        "properties": {
          "codigo": {
            "description": "fallo_conexion y rechazo_conexion: el código numérico de WhatsApp; stream_error: un código corto (texto)."
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "intentos": {
            "description": "sin_conexion: los intentos de reconexión del SDK que fallaron.",
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "enum": [
              "sin_conexion",
              "cliente_desactualizado",
              "fallo_conexion",
              "rechazo_conexion",
              "stream_error",
              "dispositivo_ausente"
            ],
            "type": "string"
          },
          "permanente": {
            "description": "true: no se resuelve reintentando (hace falta otra versión, volver a vincular o que alguien lo pida).",
            "type": "boolean"
          }
        },
        "required": [
          "motivo",
          "permanente",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosEstado": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "from_me": {
            "type": "boolean"
          },
          "mime": {
            "type": "string"
          },
          "motivo": {
            "description": "Con redactado: por qué ya no está el contenido.",
            "enum": [
              "retencion",
              "revocado",
              ""
            ],
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "redactado": {
            "description": "La historia pasó su retención o su autor la borró: el data es solo {redactado, motivo}.",
            "type": "boolean"
          },
          "retener_hasta": {
            "format": "date-time",
            "type": "string"
          },
          "status_id": {
            "type": "string"
          },
          "texto": {
            "type": "string"
          },
          "tipo": {
            "type": "string"
          },
          "vence_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status_id",
          "provider_id",
          "from_me",
          "tipo",
          "vence_en",
          "retener_hasta"
        ],
        "type": "object"
      },
      "EvDatosEstadoRevocado": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Quien lo publicó; null si es del propio número (from_me)."
          },
          "from_me": {
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          },
          "status_id": {
            "type": "string"
          }
        },
        "required": [
          "status_id",
          "autor",
          "provider_id",
          "from_me"
        ],
        "type": "object"
      },
      "EvDatosGeneracion": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosGrupoCambio": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Quien hizo el cambio, si el aviso lo dice."
          },
          "campos": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvCamposGrupo"
              }
            ],
            "description": "Solo los campos que cambiaron, con su valor nuevo."
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          }
        },
        "required": [
          "grupo",
          "campos",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosGrupoParticipantes": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Quien hizo el cambio, si el aviso lo dice."
          },
          "degradados": {
            "items": {
              "$ref": "#/components/schemas/Peer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "entran": {
            "description": "null si no entró nadie (igual las otras listas).",
            "items": {
              "$ref": "#/components/schemas/Peer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "motivo": {
            "description": "El motivo de la entrada que informó WhatsApp (p. ej. invite), si es un aviso.",
            "type": "string"
          },
          "promovidos": {
            "items": {
              "$ref": "#/components/schemas/Peer"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "salen": {
            "items": {
              "$ref": "#/components/schemas/Peer"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "grupo",
          "desde",
          "entran",
          "salen",
          "promovidos",
          "degradados"
        ],
        "type": "object"
      },
      "EvDatosGrupoUnido": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Quien lo agregó, si el aviso lo dice."
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor"
            ],
            "type": "string"
          },
          "es_comunidad": {
            "type": "boolean"
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "motivo": {
            "description": "El motivo que informó WhatsApp (p. ej. invite); puede venir vacío.",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "participantes": {
            "format": "int64",
            "type": "integer"
          },
          "tipo": {
            "description": "new: lo creó el propio número; si no, el tipo que informó WhatsApp (puede venir vacío).",
            "type": "string"
          }
        },
        "required": [
          "grupo",
          "nombre",
          "motivo",
          "tipo",
          "participantes",
          "es_comunidad",
          "desde"
        ],
        "type": "object"
      },
      "EvDatosInstanciaActualizada": {
        "additionalProperties": false,
        "properties": {
          "campos": {
            "description": "Los campos que cambiaron (sin sus valores).",
            "items": {
              "enum": [
                "nombre",
                "config.reconexion_automatica",
                "config.mensajes_por_segundo",
                "config.rafaga",
                "config.historial_dias",
                "config.historial_mensajes",
                "config.rechazar_llamadas",
                "config.historial_importar",
                "config.historial_medios",
                "config.mensaje_rechazo"
              ],
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "campos",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosLoteHistorial": {
        "additionalProperties": false,
        "properties": {
          "contenido_importado": {
            "description": "true: el contenido del lote quedó para importar (lo pidió un trabajo de historial).",
            "type": "boolean"
          },
          "conversaciones": {
            "format": "int64",
            "type": "integer"
          },
          "fragmento": {
            "format": "int64",
            "type": "integer"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "mensajes": {
            "format": "int64",
            "type": "integer"
          },
          "progreso": {
            "description": "El progreso (0-100) que informó WhatsApp. No es la historia completa.",
            "format": "int64",
            "type": "integer"
          },
          "sync_job_id": {
            "description": "El trabajo de historial al que pertenece el lote.",
            "type": "string"
          },
          "tipo_sync": {
            "description": "El tipo de lote que informó WhatsApp (INITIAL_BOOTSTRAP, RECENT, ON_DEMAND…).",
            "type": "string"
          }
        },
        "required": [
          "tipo_sync",
          "fragmento",
          "progreso",
          "conversaciones",
          "mensajes",
          "contenido_importado",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosMensaje": {
        "additionalProperties": false,
        "properties": {
          "anterior": {
            "description": "operacion estado: el estado de antes.",
            "type": "string"
          },
          "autor": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Peer"
              }
            ],
            "description": "Quien lo escribió, si no es el chat (en un grupo)."
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "contenido": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EvContenido"
              }
            ],
            "description": "Falta en un borrado, en una reacción, en un cambio de estado y cuando el contenido venció (redactado)."
          },
          "efimero": {
            "type": "boolean"
          },
          "es_grupo": {
            "type": "boolean"
          },
          "estado": {
            "description": "operacion estado: el estado nuevo del mensaje (nunca baja).",
            "enum": [
              "pendiente",
              "recibido",
              "enviado",
              "entregado",
              "leido",
              "reproducido",
              "fallido",
              ""
            ],
            "type": "string"
          },
          "estado_de_grupo": {
            "description": "Un estado publicado en un grupo.",
            "type": "boolean"
          },
          "from_me": {
            "type": "boolean"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo": {
            "description": "Con redactado: por qué ya no está el contenido.",
            "enum": [
              "vencido",
              ""
            ],
            "type": "string"
          },
          "nombre_perfil": {
            "type": "string"
          },
          "objetivo": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Referencia"
              }
            ],
            "description": "El mensaje que edita, borra, al que reacciona o la ubicación que actualiza."
          },
          "operacion": {
            "enum": [
              "mensaje",
              "edicion",
              "revocacion",
              "reaccion",
              "ubicacion_actualizada",
              "estado"
            ],
            "type": "string"
          },
          "pedido_al_telefono": {
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          },
          "reaccion": {
            "description": "message.reaction: el emoji (vacío: quitó la reacción).",
            "type": "string"
          },
          "redactado": {
            "description": "El mensaje temporal venció: el motor borró su contenido.",
            "type": "boolean"
          },
          "server_id": {
            "description": "El ID de servidor de una publicación de un canal (distinto de provider_id).",
            "format": "int64",
            "type": "integer"
          },
          "ver_una_vez": {
            "type": "boolean"
          },
          "version": {
            "description": "Edición, borrado o reacción: cuántas operaciones de ese tipo sobre el mismo mensaje llegaron hasta esta (la última es la vigente).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "chat",
          "provider_id",
          "from_me",
          "es_grupo",
          "operacion",
          "momento"
        ],
        "type": "object"
      },
      "EvDatosPrueba": {
        "additionalProperties": false,
        "properties": {
          "prueba": {
            "enum": [
              true
            ],
            "type": "boolean"
          }
        },
        "required": [
          "prueba"
        ],
        "type": "object"
      },
      "EvDatosRedactado": {
        "additionalProperties": false,
        "properties": {
          "motivo": {
            "enum": [
              "retencion",
              "revocado"
            ],
            "type": "string"
          },
          "redactado": {
            "description": "Siempre true.",
            "type": "boolean"
          }
        },
        "required": [
          "redactado",
          "motivo"
        ],
        "type": "object"
      },
      "EvDatosRetoDisponible": {
        "additionalProperties": false,
        "properties": {
          "expira_en": {
            "format": "date-time",
            "type": "string"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "modo": {
            "enum": [
              "qr",
              "codigo"
            ],
            "type": "string"
          },
          "reto": {
            "description": "El tipo de reto. El valor (el QR o el código) no viaja en el evento: se lee del emparejamiento de la instancia.",
            "enum": [
              "qr",
              "codigo",
              "passkey",
              "passkey_confirmacion"
            ],
            "type": "string"
          }
        },
        "required": [
          "modo",
          "reto",
          "expira_en",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosRetoVencido": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "enum": [
              "qr_vencido",
              "codigo_vencido"
            ],
            "type": "string"
          }
        },
        "required": [
          "motivo",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosSesionCerrada": {
        "additionalProperties": false,
        "properties": {
          "al_conectar": {
            "description": "origen telefono: la cerró el servidor al conectar.",
            "type": "boolean"
          },
          "codigo": {
            "description": "origen telefono: el código que informó WhatsApp.",
            "format": "int64",
            "type": "integer"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "origen": {
            "description": "telefono: WhatsApp cerró la sesión (desvinculada desde el teléfono); operador: se desvinculó a pedido.",
            "enum": [
              "telefono",
              "operador"
            ],
            "type": "string"
          },
          "remoto": {
            "description": "origen operador: el motor pudo avisarle a WhatsApp (el dispositivo ya no figura en el teléfono).",
            "type": "boolean"
          }
        },
        "required": [
          "origen",
          "generacion"
        ],
        "type": "object"
      },
      "EvDatosTrabajoSync": {
        "additionalProperties": false,
        "properties": {
          "aviso": {
            "type": "string"
          },
          "chat_actual": {
            "format": "int64",
            "type": "integer"
          },
          "chats": {
            "description": "Cuántos chats tiene el trabajo.",
            "format": "int64",
            "type": "integer"
          },
          "duplicados": {
            "format": "int64",
            "type": "integer"
          },
          "estado": {
            "enum": [
              "en_curso",
              "esperando",
              "en_pausa",
              "completado",
              "cancelado",
              "fallido"
            ],
            "type": "string"
          },
          "historia_completa": {
            "description": "Siempre false: WhatsApp no garantiza la historia completa.",
            "type": "boolean"
          },
          "importados": {
            "description": "Mensajes nuevos para el motor.",
            "format": "int64",
            "type": "integer"
          },
          "lotes_importados": {
            "format": "int64",
            "type": "integer"
          },
          "lotes_recibidos": {
            "format": "int64",
            "type": "integer"
          },
          "mas_nuevo_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "mas_viejo_en": {
            "description": "El mensaje más viejo importado (null: ninguno).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "motivo": {
            "description": "Por qué está en pausa o por qué terminó (contrapresion, cuota, corte, sin_mas_historial, sin_mas_lotes, chats_recorridos, pedido_atendido, sin_respuesta, sin_mensajes, fuera_del_historial, solo_en_el_telefono, pedido_rechazado, no_autorizado, importacion_apagada, cancelado…); vacío si no hay.",
            "type": "string"
          },
          "no_soportados": {
            "format": "int64",
            "type": "integer"
          },
          "omitidos_cuota": {
            "format": "int64",
            "type": "integer"
          },
          "omitidos_fecha": {
            "format": "int64",
            "type": "integer"
          },
          "pedidos": {
            "description": "Pedidos que salieron al teléfono.",
            "format": "int64",
            "type": "integer"
          },
          "progreso": {
            "description": "El último progreso (0-100) que informó WhatsApp; null si no llegó ninguno.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "sin_respuesta": {
            "description": "Pedidos que el teléfono no contestó a tiempo.",
            "format": "int64",
            "type": "integer"
          },
          "sync_job_id": {
            "description": "El mismo ID que el comando que lo creó.",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "inicial",
              "pedido",
              "importacion"
            ],
            "type": "string"
          }
        },
        "required": [
          "sync_job_id",
          "tipo",
          "estado",
          "motivo",
          "lotes_recibidos",
          "lotes_importados",
          "importados",
          "duplicados",
          "omitidos_fecha",
          "omitidos_cuota",
          "no_soportados",
          "progreso",
          "mas_viejo_en",
          "mas_nuevo_en",
          "pedidos",
          "sin_respuesta",
          "chats",
          "chat_actual",
          "historia_completa",
          "aviso"
        ],
        "type": "object"
      },
      "EvMedio": {
        "additionalProperties": false,
        "properties": {
          "alto": {
            "format": "int64",
            "type": "integer"
          },
          "ancho": {
            "format": "int64",
            "type": "integer"
          },
          "animado": {
            "description": "Sticker animado.",
            "type": "boolean"
          },
          "bytes": {
            "format": "int64",
            "type": "integer"
          },
          "duracion_seg": {
            "format": "int64",
            "type": "integer"
          },
          "estado": {
            "description": "pendiente hasta que la descarga termina (media.ready o media.failed). no_descargado: llegó por el historial y la política de la instancia no descarga su multimedia.",
            "enum": [
              "pendiente",
              "listo",
              "fallido",
              "borrado",
              "no_descargado",
              ""
            ],
            "type": "string"
          },
          "gif": {
            "type": "boolean"
          },
          "media_id": {
            "description": "La copia privada del motor: GET /v1/media/{id}.",
            "type": "string"
          },
          "mime": {
            "description": "El MIME que informó WhatsApp.",
            "type": "string"
          },
          "nombre": {
            "description": "El nombre de un documento.",
            "type": "string"
          },
          "ptt": {
            "description": "Nota de voz.",
            "type": "boolean"
          },
          "ptv": {
            "description": "Vídeo circular.",
            "type": "boolean"
          },
          "sha256": {
            "description": "El hash del archivo (hex), como lo informó WhatsApp.",
            "type": "string"
          }
        },
        "type": "object"
      },
      "EvUbicacion": {
        "additionalProperties": false,
        "properties": {
          "comentario": {
            "type": "string"
          },
          "direccion": {
            "type": "string"
          },
          "duracion_seg": {
            "description": "En vivo: cuánto se comparte, si WhatsApp lo dijo.",
            "format": "int64",
            "type": "integer"
          },
          "en_vivo": {
            "type": "boolean"
          },
          "latitud": {
            "format": "double",
            "type": "number"
          },
          "longitud": {
            "format": "double",
            "type": "number"
          },
          "nombre": {
            "type": "string"
          },
          "precision_m": {
            "description": "En vivo: metros de precisión.",
            "format": "int64",
            "type": "integer"
          },
          "rumbo": {
            "description": "En vivo: grados.",
            "format": "int64",
            "type": "integer"
          },
          "secuencia": {
            "description": "En vivo: el número de la actualización.",
            "format": "int64",
            "type": "integer"
          },
          "termina_en": {
            "description": "En vivo: el momento más la duración (WhatsApp no avisa el fin real).",
            "format": "date-time",
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "velocidad_ms": {
            "description": "En vivo: metros por segundo.",
            "format": "double",
            "type": "number"
          }
        },
        "required": [
          "latitud",
          "longitud"
        ],
        "type": "object"
      },
      "EvVistaPrevia": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "type": "string"
          },
          "titulo": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "EventoAppstateChanged": {
        "additionalProperties": false,
        "description": "Cambió el estado de un chat en WhatsApp.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosAppState"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "appstate.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoAppstateSync": {
        "additionalProperties": false,
        "description": "Cambió la sincronización de una colección del appstate.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosSync"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "appstate.sync"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoBlocklistChanged": {
        "additionalProperties": false,
        "description": "Cambió la lista de bloqueados.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosBloqueos"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "blocklist.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallAccept": {
        "additionalProperties": false,
        "description": "La llamada se aceptó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.accept"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallOffer": {
        "additionalProperties": false,
        "description": "Entra una llamada.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.offer"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallOfferNotice": {
        "additionalProperties": false,
        "description": "Aviso de una llamada entrante.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.offer_notice"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallPreaccept": {
        "additionalProperties": false,
        "description": "La llamada se preaceptó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.preaccept"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallReject": {
        "additionalProperties": false,
        "description": "WhatsApp informó el rechazo de la llamada.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.reject"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallRejected": {
        "additionalProperties": false,
        "description": "El motor rechazó una llamada.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.rejected"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallSignal": {
        "additionalProperties": false,
        "description": "Otra señal de llamada.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.signal"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCallTerminate": {
        "additionalProperties": false,
        "description": "La llamada terminó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosLlamada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "call.terminate"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoChatEphemeral": {
        "additionalProperties": false,
        "description": "Cambió el temporizador de mensajes temporales de un chat.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosTemporizador"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "chat.ephemeral"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoChatNote": {
        "additionalProperties": false,
        "description": "Cambió la nota de un chat de WhatsApp Business.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosNota"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "chat.note"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCommandAccepted": {
        "additionalProperties": false,
        "description": "Un comando quedó aceptado.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosComandoAceptado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "command.accepted"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCommandAmbiguous": {
        "additionalProperties": false,
        "description": "No se sabe si el comando tuvo efecto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosComandoFallido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "command.ambiguous"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCommandCancelled": {
        "additionalProperties": false,
        "description": "Un comando se canceló.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosComandoCancelado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "command.cancelled"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCommandFailed": {
        "additionalProperties": false,
        "description": "Un comando falló.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosComandoFallido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "command.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoCommunityChanged": {
        "additionalProperties": false,
        "description": "Un grupo entró a una comunidad o salió de ella.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosComunidadCambio"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "community.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoConnected": {
        "additionalProperties": false,
        "description": "La sesión se conectó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosGeneracion"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "connected"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoContactAbout": {
        "additionalProperties": false,
        "description": "Cambió el recado (about) de un contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosContacto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "contact.about"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoContactBusinessName": {
        "additionalProperties": false,
        "description": "Cambió el nombre de negocio de un contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosContacto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "contact.business_name"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoContactPicture": {
        "additionalProperties": false,
        "description": "Cambió la foto de perfil de un contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosContacto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "contact.picture"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoContactPushName": {
        "additionalProperties": false,
        "description": "Cambió el nombre que manda un contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosContacto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "contact.push_name"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoContactUpdated": {
        "additionalProperties": false,
        "description": "Cambió un contacto en la libreta del teléfono.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosContacto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "contact.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoDisconnected": {
        "additionalProperties": false,
        "description": "La sesión se desconectó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosDesconectado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "disconnected"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoError": {
        "additionalProperties": false,
        "description": "Un error de conexión o de sesión.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosError"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "error"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoGroupChanged": {
        "additionalProperties": false,
        "description": "Cambió la información o los ajustes de un grupo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosGrupoCambio"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "group.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoGroupJoined": {
        "additionalProperties": false,
        "description": "El número entró a un grupo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosGrupoUnido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "group.joined"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoGroupParticipants": {
        "additionalProperties": false,
        "description": "Cambiaron los participantes de un grupo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosGrupoParticipantes"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "group.participants"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoHistorySync": {
        "additionalProperties": false,
        "description": "Llegó un lote de historial del teléfono.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosLoteHistorial"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "history.sync"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoInstanceUpdated": {
        "additionalProperties": false,
        "description": "Cambió el nombre o la configuración de la instancia.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosInstanciaActualizada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "instance.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoInteractiveResponse": {
        "additionalProperties": false,
        "description": "Alguien respondió a un mensaje interactivo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosRespuesta"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "interactive.response"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoInteractiveResponseUpdated": {
        "additionalProperties": false,
        "description": "Cambió la correlación de una respuesta ya publicada.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosRespuestaRevisada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "interactive.response.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoInteractiveUnknown": {
        "additionalProperties": false,
        "description": "Llegó una respuesta interactiva que no se pudo leer.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosRespuesta"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "interactive.unknown"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLabelAssociated": {
        "additionalProperties": false,
        "description": "Se puso una etiqueta en un chat o un mensaje.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosAsociacion"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "label.associated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLabelCreated": {
        "additionalProperties": false,
        "description": "Se creó una etiqueta de WhatsApp Business.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEtiqueta"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "label.created"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLabelDeleted": {
        "additionalProperties": false,
        "description": "Se eliminó una etiqueta.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEtiqueta"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "label.deleted"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLabelDissociated": {
        "additionalProperties": false,
        "description": "Se quitó una etiqueta de un chat o un mensaje.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosAsociacion"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "label.dissociated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLabelUpdated": {
        "additionalProperties": false,
        "description": "Se editó una etiqueta.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEtiqueta"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "label.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoLoggedOut": {
        "additionalProperties": false,
        "description": "La sesión se cerró y el vínculo ya no sirve.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosSesionCerrada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "logged_out"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMediaFailed": {
        "additionalProperties": false,
        "description": "No se pudo obtener un medio.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEvento"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "media.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMediaReady": {
        "additionalProperties": false,
        "description": "Un medio quedó listo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEvento"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "media.ready"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageExpired": {
        "additionalProperties": false,
        "description": "Venció un mensaje temporal.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosVencido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.expired"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageReaction": {
        "additionalProperties": false,
        "description": "Alguien reaccionó a un mensaje.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosMensaje"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.reaction"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageReceived": {
        "additionalProperties": false,
        "description": "Llegó un mensaje (o el eco de uno propio).",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosMensaje"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.received"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageRevoked": {
        "additionalProperties": false,
        "description": "Un mensaje se borró para todos.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosMensaje"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.revoked"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageSent": {
        "additionalProperties": false,
        "description": "WhatsApp aceptó un envío del motor.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosEnviado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.sent"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageUndecryptable": {
        "additionalProperties": false,
        "description": "Llegó un mensaje que no se pudo descifrar.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosIndescifrable"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.undecryptable"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoMessageUpdated": {
        "additionalProperties": false,
        "description": "Un mensaje cambió: edición, estado o ubicación en vivo.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosMensaje"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "message.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoNewsletterChanged": {
        "additionalProperties": false,
        "description": "Cambió la información de un canal.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCanalCambio"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "newsletter.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoNewsletterJoined": {
        "additionalProperties": false,
        "description": "El número empezó a seguir un canal.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCanalUnido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "newsletter.joined"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoNewsletterLeft": {
        "additionalProperties": false,
        "description": "El número dejó de seguir un canal.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCanalSalida"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "newsletter.left"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoNewsletterMuted": {
        "additionalProperties": false,
        "description": "Se silenció o se reactivó un canal.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCanalSilencio"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "newsletter.muted"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoNewsletterUpdates": {
        "additionalProperties": false,
        "description": "Cambiaron las vistas o las reacciones de publicaciones.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCanalContadores"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "newsletter.updates"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPaired": {
        "additionalProperties": false,
        "description": "El teléfono se vinculó.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosEmparejado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "paired"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPairingAvailable": {
        "additionalProperties": false,
        "description": "Hay un reto de emparejamiento para mostrar.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosRetoDisponible"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "pairing.available"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPairingExpired": {
        "additionalProperties": false,
        "description": "Venció el intento de emparejamiento.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosRetoVencido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "pairing.expired"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPairingFailed": {
        "additionalProperties": false,
        "description": "El intento de emparejamiento falló.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosEmparejamientoFallido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "pairing.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPeerMerged": {
        "additionalProperties": false,
        "description": "Dos peers resultaron el mismo contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosPeerUnido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "peer.merged"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPollVote": {
        "additionalProperties": false,
        "description": "Alguien votó en una encuesta.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosVoto"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "poll.vote"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPresence": {
        "additionalProperties": false,
        "description": "Cambió la presencia de un contacto suscrito.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosPresencia"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "presence"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoPrivacyChanged": {
        "additionalProperties": false,
        "description": "Cambió la privacidad del número.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosPrivacidad"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "privacy.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoProfileUpdated": {
        "additionalProperties": false,
        "description": "Cambió el perfil propio del número.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosPerfil"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "profile.updated"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoProviderUnknown": {
        "additionalProperties": false,
        "description": "Un evento del proveedor que el motor no clasifica.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosDesconocido"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "provider.unknown"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoQueryCompleted": {
        "additionalProperties": false,
        "description": "Terminó una consulta comercial.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosConsultaCompletada"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "query.completed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoQueryFailed": {
        "additionalProperties": false,
        "description": "Falló una consulta comercial.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosConsultaFallida"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "query.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoReceipt": {
        "additionalProperties": false,
        "description": "Llegó un receipt de uno o más mensajes.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/DatosRecibo"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "receipt"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoStateChanged": {
        "additionalProperties": false,
        "description": "Cambió el estado observado de la instancia.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosCambioEstado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "state.changed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoStatusReceived": {
        "additionalProperties": false,
        "description": "Llegó un status (historia) de un contacto.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "description": "La forma normal o, pasada la retención, solo la marca de redacción.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/EvDatosEstado"
              },
              {
                "$ref": "#/components/schemas/EvDatosRedactado"
              }
            ]
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "status.received"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoStatusRevoked": {
        "additionalProperties": false,
        "description": "Se borró un status.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosEstadoRevocado"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "status.revoked"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoStreamReplaced": {
        "additionalProperties": false,
        "description": "Otra conexión tomó la sesión.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosGeneracion"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "stream_replaced"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoSyncCompleted": {
        "additionalProperties": false,
        "description": "Terminó un trabajo de historial.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosTrabajoSync"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "sync.completed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoSyncFailed": {
        "additionalProperties": false,
        "description": "Un trabajo de historial se canceló o falló.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosTrabajoSync"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "sync.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoSyncProgress": {
        "additionalProperties": false,
        "description": "Avanzó un trabajo de historial.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosTrabajoSync"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "sync.progress"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoTemporaryBan": {
        "additionalProperties": false,
        "description": "WhatsApp bloqueó el número temporalmente.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosBaneo"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "temporary_ban"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "EventoWebhookTest": {
        "additionalProperties": false,
        "description": "Una entrega de prueba.",
        "properties": {
          "command_id": {
            "description": "Solo si el evento es efecto de un comando: el comando que lo causó.",
            "type": "string"
          },
          "correlation_id": {
            "description": "Solo si el comando lo traía: tu identificador, de vuelta.",
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/EvDatosPrueba"
          },
          "event_id": {
            "description": "Identificador único del evento: deduplica por este campo (un reintento o un replay trae el mismo).",
            "examples": [
              "e1f0c2d4-0000-4000-8000-000000001187"
            ],
            "type": "string"
          },
          "generation": {
            "description": "La generación de la instancia: cambia cada vez que se vuelve a vincular.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "description": "La instancia a la que le pasó. La app dueña no viaja: la dice tu credencial o la suscripción.",
            "examples": [
              "8a1d2c3e-0000-4000-8000-0000000000a1"
            ],
            "type": "string"
          },
          "occurred_at": {
            "description": "Cuándo pasó (según WhatsApp o el motor).",
            "examples": [
              "2026-10-24T15:08:12Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "origin": {
            "description": "`live` (en vivo), `history` (importado del historial) u `operator` (un comando o una acción del motor).",
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "received_at": {
            "description": "Cuándo lo aceptó el motor.",
            "examples": [
              "2026-10-24T15:08:13Z"
            ],
            "format": "date-time",
            "type": "string"
          },
          "schema_version": {
            "description": "La versión del esquema del evento. Hoy, siempre 1.",
            "examples": [
              1
            ],
            "format": "int64",
            "type": "integer"
          },
          "seq": {
            "description": "Posición en el ledger de la instancia: crece de uno en uno, sin huecos. Es el orden de commit del motor, no el de WhatsApp.",
            "examples": [
              1187
            ],
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "description": "El tipo de evento.",
            "enum": [
              "webhook.test"
            ],
            "type": "string"
          }
        },
        "required": [
          "schema_version",
          "event_id",
          "instance_id",
          "seq",
          "type",
          "occurred_at",
          "received_at",
          "generation",
          "origin",
          "data"
        ],
        "type": "object"
      },
      "Fila": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "maxLength": 72,
            "type": "string"
          },
          "id": {
            "description": "El ID que vuelve en la respuesta (único en la lista).",
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "titulo": {
            "maxLength": 24,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "id",
          "titulo"
        ],
        "type": "object"
      },
      "FotoContacto": {
        "additionalProperties": false,
        "properties": {
          "estado": {
            "description": "oculta: su privacidad no se la muestra a este número (no es un error).",
            "enum": [
              "disponible",
              "oculta",
              "sin_foto"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "tipo": {
            "enum": [
              "image",
              "preview",
              ""
            ],
            "type": "string"
          },
          "url": {
            "description": "La URL del CDN de WhatsApp: temporal (vence en horas).",
            "type": "string"
          }
        },
        "required": [
          "estado"
        ],
        "type": "object"
      },
      "FotoContactoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "cuota": {
            "$ref": "#/components/schemas/Cuota"
          },
          "foto": {
            "$ref": "#/components/schemas/FotoContacto"
          }
        },
        "required": [
          "foto",
          "cuota"
        ],
        "type": "object"
      },
      "GrupoOutputBody": {
        "additionalProperties": false,
        "properties": {
          "grupo": {
            "$ref": "#/components/schemas/GrupoWA"
          },
          "participantes": {
            "items": {
              "$ref": "#/components/schemas/ParticipanteVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "grupo",
          "participantes"
        ],
        "type": "object"
      },
      "GrupoRef": {
        "additionalProperties": false,
        "properties": {
          "jid": {
            "description": "El JID del grupo (…@g.us).",
            "maxLength": 128,
            "type": "string"
          },
          "peer_ref": {
            "description": "El peer_ref del grupo en esta instancia.",
            "type": "string"
          }
        },
        "type": "object"
      },
      "GrupoWA": {
        "additionalProperties": false,
        "properties": {
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "anuncio": {
            "description": "Solo los administradores escriben.",
            "type": "boolean"
          },
          "aprobacion": {
            "description": "Entrar exige la aprobación de un administrador.",
            "type": "boolean"
          },
          "bloqueado": {
            "description": "Solo los administradores editan la información.",
            "type": "boolean"
          },
          "comunidad": {
            "$ref": "#/components/schemas/Peer"
          },
          "consultado_en": {
            "description": "La última vez que el motor le preguntó a WhatsApp por este grupo.",
            "format": "date-time",
            "type": "string"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "creador": {
            "$ref": "#/components/schemas/Peer"
          },
          "descripcion": {
            "type": "string"
          },
          "descripcion_en": {
            "format": "date-time",
            "type": "string"
          },
          "efimero_seg": {
            "format": "int64",
            "type": "integer"
          },
          "eliminado_en": {
            "format": "date-time",
            "type": "string"
          },
          "es_comunidad": {
            "type": "boolean"
          },
          "foto_id": {
            "type": "string"
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "invitacion": {
            "description": "El último enlace de invitación que obtuvo el motor (solo un administrador lo puede pedir).",
            "type": "string"
          },
          "invitacion_en": {
            "format": "date-time",
            "type": "string"
          },
          "miembro": {
            "description": "false: el número salió o lo sacaron.",
            "type": "boolean"
          },
          "modo_agregar": {
            "description": "admin_add o all_member_add.",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "nombre_en": {
            "format": "date-time",
            "type": "string"
          },
          "participantes": {
            "format": "int64",
            "type": "integer"
          },
          "rol_propio": {
            "description": "El rol del número en el grupo (los permisos remotos).",
            "enum": [
              "miembro",
              "admin",
              "superadmin"
            ],
            "type": "string"
          },
          "subgrupo_por_defecto": {
            "description": "El grupo de anuncios de su comunidad.",
            "type": "boolean"
          },
          "suspendido": {
            "type": "boolean"
          },
          "version": {
            "description": "Sube con cada cambio de esta fila.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "grupo",
          "nombre",
          "descripcion",
          "anuncio",
          "bloqueado",
          "aprobacion",
          "efimero_seg",
          "es_comunidad",
          "participantes",
          "miembro",
          "rol_propio",
          "suspendido",
          "version",
          "actualizado_en"
        ],
        "type": "object"
      },
      "GruposOutputBody": {
        "additionalProperties": false,
        "properties": {
          "grupos": {
            "items": {
              "$ref": "#/components/schemas/GrupoWA"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "grupos",
          "has_more"
        ],
        "type": "object"
      },
      "HorarioComercial": {
        "additionalProperties": false,
        "properties": {
          "abre": {
            "description": "Minutos desde la medianoche, como texto (specific_hours).",
            "type": "string"
          },
          "cierra": {
            "type": "string"
          },
          "dia": {
            "description": "El día, como lo informa WhatsApp (sun, mon…).",
            "type": "string"
          },
          "modo": {
            "description": "specific_hours, open_24h o appointment_only, como lo informa WhatsApp.",
            "type": "string"
          }
        },
        "required": [
          "dia",
          "modo"
        ],
        "type": "object"
      },
      "Identidad": {
        "additionalProperties": false,
        "properties": {
          "aliases": {
            "examples": [
              [
                "CONTACTO@lid"
              ]
            ],
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "clase": {
            "examples": [
              "usuario"
            ],
            "type": "string"
          },
          "contacto": {
            "description": "Si es un contacto de transporte del número (GET contacts).",
            "type": "boolean"
          },
          "jid": {
            "type": "string"
          },
          "lid": {
            "description": "Su LID, si está comprobado en esta instancia.",
            "type": "string"
          },
          "peer_ref": {
            "type": "string"
          },
          "pn": {
            "description": "Su JID de teléfono (s.whatsapp.net), si está comprobado en esta instancia.",
            "type": "string"
          },
          "telefono": {
            "description": "El teléfono del PN comprobado. Un LID solo nunca da un teléfono.",
            "type": "string"
          }
        },
        "required": [
          "contacto",
          "peer_ref",
          "jid",
          "clase",
          "aliases"
        ],
        "type": "object"
      },
      "ImagenProducto": {
        "additionalProperties": false,
        "properties": {
          "original_url": {
            "type": "string"
          },
          "solicitada_url": {
            "description": "La imagen al tamaño pedido (100 × 100).",
            "type": "string"
          }
        },
        "type": "object"
      },
      "ImportarHistorial": {
        "additionalProperties": false,
        "properties": {
          "chats": {
            "description": "Los chats (vacío: los 20 con actividad más reciente que el motor conoce).",
            "items": {
              "$ref": "#/components/schemas/Destino"
            },
            "maxItems": 50,
            "type": [
              "array",
              "null"
            ]
          },
          "dias": {
            "description": "Lo más viejo que se importa (de fábrica, el de la política de la instancia).",
            "format": "int64",
            "maximum": 3650,
            "minimum": 1,
            "type": "integer"
          },
          "max_mensajes": {
            "description": "La cuota de este trabajo (como mucho, la de la política).",
            "format": "int64",
            "maximum": 100000,
            "minimum": 1,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "InfoContacto": {
        "additionalProperties": false,
        "properties": {
          "dispositivos": {
            "description": "Cuántos dispositivos tiene vinculados.",
            "format": "int64",
            "type": "integer"
          },
          "foto_id": {
            "description": "El ID de su foto (la imagen: GET …/contacts/picture).",
            "type": "string"
          },
          "jid": {
            "type": "string"
          },
          "lid": {
            "type": "string"
          },
          "negocio": {
            "type": "boolean"
          },
          "nombre_verificado": {
            "type": "string"
          },
          "peer_ref": {
            "description": "Si la instancia ya lo conocía: su peer estable.",
            "type": "string"
          },
          "recado": {
            "description": "Su «info» (about), si lo comparte con este número.",
            "type": "string"
          }
        },
        "required": [
          "jid",
          "dispositivos"
        ],
        "type": "object"
      },
      "InfoContactosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "cuota": {
            "$ref": "#/components/schemas/Cuota"
          },
          "perfiles": {
            "description": "Los que el servidor devolvió (un usuario sin cuenta no aparece).",
            "items": {
              "$ref": "#/components/schemas/InfoContacto"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "perfiles",
          "cuota"
        ],
        "type": "object"
      },
      "Instancia": {
        "additionalProperties": false,
        "properties": {
          "actualizada_en": {
            "format": "date-time",
            "type": "string"
          },
          "archivada_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "bloqueada_hasta": {
            "description": "Fin del baneo temporal, si WhatsApp lo informó.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "caida_desde": {
            "description": "Desde cuándo está caída sin quererlo.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "canario": {
            "description": "La instancia va con el proceso canario (una versión nueva) mientras haya uno corriendo.",
            "type": "boolean"
          },
          "checked_at": {
            "description": "Última vez que el motor verificó el estado contra la sesión real.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "cliente_id": {
            "type": "string"
          },
          "conectada_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "config": {
            "$ref": "#/components/schemas/ConfigInstancia"
          },
          "creada_en": {
            "format": "date-time",
            "type": "string"
          },
          "estado": {
            "examples": [
              "conectado"
            ],
            "type": "string"
          },
          "estado_deseado": {
            "enum": [
              "activo",
              "pausado",
              "desvinculado",
              "archivado"
            ],
            "type": "string"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "motivo": {
            "examples": [
              ""
            ],
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "numero": {
            "examples": [
              "+NUMERO_DE_TU_TELEFONO"
            ],
            "type": "string"
          },
          "owner_ref": {
            "examples": [
              "empresa-42"
            ],
            "type": "string"
          },
          "proveedor": {
            "examples": [
              "whatsmeow"
            ],
            "type": "string"
          },
          "proximo_intento_en": {
            "description": "Próximo intento de reconexión del conciliador.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "proxy_id": {
            "description": "El proxy de transporte de la instancia (Ajustes → Proxies); null, directo.",
            "type": "string"
          },
          "reconexiones": {
            "format": "int64",
            "type": "integer"
          },
          "ultimo_error": {
            "description": "Código del último error tipificado (vacío si no hubo).",
            "examples": [
              ""
            ],
            "type": "string"
          },
          "ultimo_error_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "format": "int64",
            "type": "integer"
          },
          "vinculada_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "cliente_id",
          "owner_ref",
          "nombre",
          "proveedor",
          "estado_deseado",
          "estado",
          "motivo",
          "version",
          "generacion",
          "vinculada_en",
          "conectada_en",
          "checked_at",
          "creada_en",
          "actualizada_en",
          "config",
          "ultimo_error",
          "ultimo_error_en",
          "caida_desde",
          "bloqueada_hasta",
          "proximo_intento_en",
          "reconexiones",
          "archivada_en",
          "proxy_id",
          "canario",
          "numero"
        ],
        "type": "object"
      },
      "IntentoAceptado": {
        "additionalProperties": false,
        "properties": {
          "estado": {
            "type": "string"
          },
          "fase": {
            "type": "string"
          },
          "generacion": {
            "format": "int64",
            "type": "integer"
          },
          "instancia_id": {
            "type": "string"
          },
          "modo": {
            "enum": [
              "qr",
              "codigo"
            ],
            "type": "string"
          }
        },
        "required": [
          "instancia_id",
          "generacion",
          "modo",
          "fase",
          "estado"
        ],
        "type": "object"
      },
      "Interactivo": {
        "additionalProperties": false,
        "properties": {
          "boton_lista": {
            "description": "list: el texto del botón que abre la lista.",
            "maxLength": 20,
            "type": "string"
          },
          "botones": {
            "description": "buttons: hasta 3 de responder (reply), o hasta 2 entre copy, url y call, o un solo pix. No se mezclan las respuestas con los otros.",
            "items": {
              "$ref": "#/components/schemas/Boton"
            },
            "maxItems": 3,
            "type": [
              "array",
              "null"
            ]
          },
          "cuerpo": {
            "description": "El texto del mensaje.",
            "maxLength": 1024,
            "minLength": 1,
            "type": "string"
          },
          "encabezado": {
            "description": "El título (buttons y list).",
            "maxLength": 60,
            "type": "string"
          },
          "pie": {
            "description": "El texto chico del final (buttons y list).",
            "maxLength": 60,
            "type": "string"
          },
          "respaldo_texto": {
            "description": "list: cuando WhatsApp acepta la lista, el motor manda además al mismo chat un texto con las opciones numeradas («1. Manzana»…). Si alguien de ese chat contesta solo con uno de esos números en las 24 horas siguientes, llega también un interactive.response correlacionado con su fila, con via texto. iOS no muestra las listas: con un remitente normal dice «no compatible» y con un Business no aparece nada. Con 3 opciones o menos conviene la variante buttons (reply).",
            "type": "boolean"
          },
          "secciones": {
            "description": "list: de 1 a 10 secciones, con 10 filas en total como máximo.",
            "items": {
              "$ref": "#/components/schemas/Seccion"
            },
            "maxItems": 10,
            "type": [
              "array",
              "null"
            ]
          },
          "tarjetas": {
            "description": "carousel: de 2 a 10 tarjetas.",
            "items": {
              "$ref": "#/components/schemas/Tarjeta"
            },
            "maxItems": 10,
            "type": [
              "array",
              "null"
            ]
          },
          "variante": {
            "description": "buttons (de 1 a 3 botones), list (una lista con secciones y filas) o carousel (de 2 a 10 tarjetas).",
            "enum": [
              "buttons",
              "list",
              "carousel"
            ],
            "type": "string"
          }
        },
        "required": [
          "variante",
          "cuerpo"
        ],
        "type": "object"
      },
      "InvitacionInfo": {
        "additionalProperties": false,
        "properties": {
          "aprobacion": {
            "description": "Entrar exige la aprobación de un administrador.",
            "type": "boolean"
          },
          "comunidad": {
            "type": "string"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "descripcion": {
            "type": "string"
          },
          "es_comunidad": {
            "type": "boolean"
          },
          "jid": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "participantes": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "jid",
          "nombre",
          "participantes",
          "es_comunidad",
          "aprobacion"
        ],
        "type": "object"
      },
      "InvitacionesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "comandos": {
            "items": {
              "$ref": "#/components/schemas/Comando"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "enlace": {
            "type": "string"
          }
        },
        "required": [
          "enlace",
          "comandos"
        ],
        "type": "object"
      },
      "KeepAlive": {
        "additionalProperties": false,
        "properties": {
          "errores_seguidos": {
            "format": "int64",
            "type": "integer"
          },
          "ultima_vuelta": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "ultimo_fallo": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "errores_seguidos",
          "ultimo_fallo",
          "ultima_vuelta"
        ],
        "type": "object"
      },
      "ListaEntregasOutputBody": {
        "additionalProperties": false,
        "properties": {
          "elementos": {
            "items": {
              "$ref": "#/components/schemas/VistaEntrega"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pagina": {
            "format": "int64",
            "type": "integer"
          },
          "por_pagina": {
            "format": "int64",
            "type": "integer"
          },
          "total": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "elementos",
          "total",
          "pagina",
          "por_pagina"
        ],
        "type": "object"
      },
      "ListaEventosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "events": {
            "items": {
              "$ref": "#/components/schemas/Envelope"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_after_seq": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "events",
          "next_after_seq",
          "has_more"
        ],
        "type": "object"
      },
      "ListaInstanciasV1OutputBody": {
        "additionalProperties": false,
        "properties": {
          "elementos": {
            "items": {
              "$ref": "#/components/schemas/Instancia"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pagina": {
            "format": "int64",
            "type": "integer"
          },
          "por_pagina": {
            "format": "int64",
            "type": "integer"
          },
          "total": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "elementos",
          "total",
          "pagina",
          "por_pagina"
        ],
        "type": "object"
      },
      "ListaSuscripcionesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "elementos": {
            "items": {
              "$ref": "#/components/schemas/Vista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "elementos"
        ],
        "type": "object"
      },
      "LlamadaVista": {
        "additionalProperties": false,
        "properties": {
          "actualizada_en": {
            "format": "date-time",
            "type": "string"
          },
          "call_id": {
            "type": "string"
          },
          "de": {
            "$ref": "#/components/schemas/Peer"
          },
          "estado": {
            "enum": [
              "entrante",
              "aceptada",
              "terminada",
              "rechazada"
            ],
            "type": "string"
          },
          "motivo": {
            "type": "string"
          },
          "rechazo": {
            "enum": [
              "automatico",
              "operador",
              "app",
              ""
            ],
            "type": "string"
          },
          "recibida_en": {
            "format": "date-time",
            "type": "string"
          },
          "video": {
            "type": "boolean"
          }
        },
        "required": [
          "call_id",
          "de",
          "video",
          "estado",
          "recibida_en",
          "actualizada_en"
        ],
        "type": "object"
      },
      "LlamadasOutputBody": {
        "additionalProperties": false,
        "properties": {
          "llamadas": {
            "items": {
              "$ref": "#/components/schemas/LlamadaVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "llamadas"
        ],
        "type": "object"
      },
      "Medio": {
        "additionalProperties": false,
        "properties": {
          "bytes": {
            "format": "int64",
            "type": "integer"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "descarga": {
            "$ref": "#/components/schemas/Permiso"
          },
          "estado": {
            "enum": [
              "pendiente",
              "subiendo",
              "listo",
              "fallido",
              "borrado"
            ],
            "type": "string"
          },
          "instance_id": {
            "type": "string"
          },
          "media_id": {
            "type": "string"
          },
          "metadatos": {
            "$ref": "#/components/schemas/Metadatos"
          },
          "mime": {
            "description": "El MIME real, detectado por el contenido.",
            "type": "string"
          },
          "mime_declarado": {
            "type": "string"
          },
          "motivo": {
            "description": "Por qué falló o se borró (código): pedido, retencion, mensaje_vencido (el mensaje temporal que lo trajo o lo mandó venció)…",
            "type": "string"
          },
          "nombre_archivo": {
            "type": "string"
          },
          "origen": {
            "enum": [
              "subida",
              "url",
              "entrante",
              "conversion"
            ],
            "type": "string"
          },
          "retencion_hasta": {
            "description": "Después, el archivo se borra (salvo que lo use un envío pendiente).",
            "format": "date-time",
            "type": "string"
          },
          "sha256": {
            "type": "string"
          },
          "trabajo": {
            "$ref": "#/components/schemas/ProgresoMedio"
          }
        },
        "required": [
          "media_id",
          "instance_id",
          "origen",
          "estado",
          "bytes",
          "metadatos",
          "created_at"
        ],
        "type": "object"
      },
      "MedioComando": {
        "additionalProperties": false,
        "properties": {
          "estado": {
            "enum": [
              "pendiente",
              "subiendo",
              "listo",
              "fallido",
              "borrado"
            ],
            "type": "string"
          },
          "media_id": {
            "type": "string"
          },
          "motivo": {
            "description": "Por qué falló: formato_no_convertible, tiempo_excedido, memoria_excedida, url_rechazada…",
            "type": "string"
          }
        },
        "required": [
          "media_id",
          "estado"
        ],
        "type": "object"
      },
      "MedioRef": {
        "additionalProperties": false,
        "properties": {
          "media_id": {
            "description": "Un medio de esta instancia (POST /v1/instances/{id}/media/uploads), listo.",
            "type": "string"
          },
          "nombre_archivo": {
            "description": "El nombre que ve el destinatario (documentos).",
            "maxLength": 200,
            "type": "string"
          },
          "url": {
            "description": "Una URL http(s) cuyo host está en los destinos permitidos (los mismos de los webhooks). El motor la descarga como un trabajo durable.",
            "maxLength": 2000,
            "type": "string"
          }
        },
        "type": "object"
      },
      "MedioTarjeta": {
        "additionalProperties": false,
        "properties": {
          "media_id": {
            "description": "Un medio de esta instancia (POST /v1/instances/{id}/media/uploads), listo.",
            "type": "string"
          }
        },
        "required": [
          "media_id"
        ],
        "type": "object"
      },
      "MensajeOutputBody": {
        "additionalProperties": false,
        "properties": {
          "mensaje": {
            "$ref": "#/components/schemas/MensajeStore"
          },
          "recibos": {
            "description": "Los receipts por destinatario (en un grupo, cada participante).",
            "items": {
              "$ref": "#/components/schemas/ReciboVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "mensaje",
          "recibos"
        ],
        "type": "object"
      },
      "MensajeStore": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "command_id": {
            "type": "string"
          },
          "contenido": {
            "description": "El contenido normalizado: el mismo de su message.received (texto, medio, ubicación…). Una ubicacion_en_vivo trae en ubicacion: en_vivo, latitud, longitud, precision_m, velocidad_ms, rumbo, secuencia, comentario y, si WhatsApp mandó la duración, duracion_seg (los segundos que se comparte) y termina_en (RFC 3339: el momento más la duración; WhatsApp no le avisa el fin real a un dispositivo vinculado). Un contactos trae en cada contacto nombre, vcard y telefonos (los de la vCard). Un mensaje de un estado de grupo trae estado_de_grupo en su message.received."
          },
          "contenido_disponible": {
            "description": "false: el mensaje temporal venció, el evento ya no está (retención de lo entregado) o el mensaje no tiene contenido.",
            "type": "boolean"
          },
          "estado": {
            "description": "recibido, enviado, entregado, leido, reproducido (solo sube), pendiente o fallido.",
            "type": "string"
          },
          "event_id": {
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "message_ref": {
            "description": "La referencia del motor (estable).",
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo_no_disponible": {
            "description": "Por qué contenido_disponible es false: vencido (era un mensaje temporal y pasó su vencimiento: el motor borró su contenido y sus medios, y emitió message.expired) o retencion (su evento ya no está). Sin el campo: no tiene contenido (una revocación, por ejemplo).",
            "enum": [
              "vencido",
              "retencion"
            ],
            "type": "string"
          },
          "objetivo_provider_id": {
            "description": "El mensaje que edita, borra o al que reacciona.",
            "type": "string"
          },
          "operacion": {
            "enum": [
              "mensaje",
              "edicion",
              "revocacion",
              "reaccion",
              "indescifrable"
            ],
            "type": "string"
          },
          "origen": {
            "enum": [
              "live",
              "history",
              "operator"
            ],
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "reaccion": {
            "type": "string"
          },
          "tipo_contenido": {
            "type": "string"
          },
          "vence_en": {
            "description": "Solo un mensaje temporal (o su edición): su momento más expiracion_seg. Al pasarlo, el motor borra su contenido.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "message_ref",
          "chat",
          "provider_id",
          "from_me",
          "operacion",
          "tipo_contenido",
          "estado",
          "origen",
          "momento",
          "contenido_disponible"
        ],
        "type": "object"
      },
      "MensajeVista": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "from_me": {
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          }
        },
        "required": [
          "provider_id",
          "from_me"
        ],
        "type": "object"
      },
      "MensajesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "mensajes": {
            "items": {
              "$ref": "#/components/schemas/MensajeStore"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "required": [
          "mensajes",
          "has_more"
        ],
        "type": "object"
      },
      "Metadatos": {
        "additionalProperties": false,
        "properties": {
          "alto": {
            "format": "int64",
            "type": "integer"
          },
          "ancho": {
            "format": "int64",
            "type": "integer"
          },
          "animado": {
            "type": "boolean"
          },
          "duracion_seg": {
            "format": "int64",
            "type": "integer"
          },
          "forma_onda": {
            "items": {
              "format": "int64",
              "type": "integer"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "type": "object"
      },
      "MotivoOpcional": {
        "additionalProperties": false,
        "properties": {
          "motivo": {
            "description": "Por qué (queda en la auditoría; un token o un teléfono pegados aquí se ocultan).",
            "maxLength": 300,
            "type": "string"
          }
        },
        "type": "object"
      },
      "MultimediaDiag": {
        "additionalProperties": false,
        "properties": {
          "almacenamiento": {
            "enum": [
              "disponible",
              "deshabilitada",
              "no_disponible"
            ],
            "type": "string"
          },
          "fallidos_24h": {
            "format": "int64",
            "type": "integer"
          },
          "pendientes": {
            "description": "Descargas e importaciones que esperan.",
            "format": "int64",
            "type": "integer"
          },
          "presion_disco": {
            "type": "boolean"
          }
        },
        "required": [
          "almacenamiento",
          "presion_disco",
          "pendientes",
          "fallidos_24h"
        ],
        "type": "object"
      },
      "NotaVista": {
        "additionalProperties": false,
        "properties": {
          "creada_en": {
            "format": "date-time",
            "type": "string"
          },
          "eliminada": {
            "type": "boolean"
          },
          "nota_id": {
            "description": "El ID de la nota en WhatsApp.",
            "type": "string"
          },
          "texto": {
            "description": "Vacío si se eliminó.",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "no_estructurada",
              "estructurada"
            ],
            "type": "string"
          }
        },
        "required": [
          "nota_id",
          "tipo",
          "eliminada"
        ],
        "type": "object"
      },
      "Objetivo": {
        "additionalProperties": false,
        "properties": {
          "provider_id": {
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "provider_id"
        ],
        "type": "object"
      },
      "OpcionResultado": {
        "additionalProperties": false,
        "properties": {
          "opcion": {
            "type": "string"
          },
          "votos": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "opcion",
          "votos"
        ],
        "type": "object"
      },
      "PIX": {
        "additionalProperties": false,
        "properties": {
          "clave": {
            "description": "La clave entera en el formato de su tipo (si no, 422 con el campo): phone, + y de 8 a 15 dígitos (admite espacios, guiones y paréntesis); email, solo la dirección; cpf, 11 dígitos o 000.000.000-00; cnpj, 14 caracteres o 00.000.000/0000-00, numérico o alfanumérico (los 12 primeros, dígitos o letras A-Z en mayúsculas; los 2 verificadores, dígitos); cpf y cnpj con sus dígitos verificadores y sin otra puntuación; random, el UUID con sus guiones. Se guarda y se manda en su forma canónica: phone con + y solo dígitos, email y random en minúsculas, cpf solo dígitos y cnpj sin puntuación (las letras, en mayúsculas).",
            "maxLength": 77,
            "minLength": 1,
            "type": "string"
          },
          "comercio": {
            "description": "El nombre que ve quien paga.",
            "maxLength": 100,
            "minLength": 1,
            "type": "string"
          },
          "tipo_clave": {
            "enum": [
              "phone",
              "email",
              "cpf",
              "cnpj",
              "random"
            ],
            "type": "string"
          }
        },
        "required": [
          "comercio",
          "clave",
          "tipo_clave"
        ],
        "type": "object"
      },
      "ParticipanteComunidad": {
        "additionalProperties": false,
        "properties": {
          "jid": {
            "type": "string"
          },
          "telefono": {
            "type": "string"
          }
        },
        "required": [
          "jid"
        ],
        "type": "object"
      },
      "ParticipanteVista": {
        "additionalProperties": false,
        "properties": {
          "cambio_en": {
            "format": "date-time",
            "type": "string"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "participante": {
            "$ref": "#/components/schemas/Peer"
          },
          "rol": {
            "enum": [
              "miembro",
              "admin",
              "superadmin"
            ],
            "type": "string"
          },
          "telefono": {
            "description": "El de su alias PN comprobado (un LID nunca se convierte en teléfono).",
            "type": "string"
          }
        },
        "required": [
          "participante",
          "rol",
          "cambio_en",
          "desde"
        ],
        "type": "object"
      },
      "ParticipantesComunidadOutputBody": {
        "additionalProperties": false,
        "properties": {
          "participantes": {
            "items": {
              "$ref": "#/components/schemas/ParticipanteComunidad"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "participantes"
        ],
        "type": "object"
      },
      "Peer": {
        "additionalProperties": false,
        "properties": {
          "aliases": {
            "examples": [
              [
                "CONTACTO@lid"
              ]
            ],
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "clase": {
            "examples": [
              "usuario"
            ],
            "type": "string"
          },
          "jid": {
            "type": "string"
          },
          "peer_ref": {
            "type": "string"
          }
        },
        "required": [
          "peer_ref",
          "jid",
          "clase",
          "aliases"
        ],
        "type": "object"
      },
      "Pendiente": {
        "additionalProperties": false,
        "properties": {
          "comandos": {
            "format": "int64",
            "type": "integer"
          },
          "eventos_sin_entregar": {
            "description": "Entregas de webhooks pendientes de esta instancia; null si ninguna suscripción la cubre.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "ultimo_seq": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "comandos",
          "eventos_sin_entregar",
          "ultimo_seq"
        ],
        "type": "object"
      },
      "PerfilComercialOutputBody": {
        "additionalProperties": false,
        "properties": {
          "areas_servicio": {
            "items": {
              "$ref": "#/components/schemas/AreaServicio"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "categorias": {
            "items": {
              "$ref": "#/components/schemas/CategoriaComercial"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "consultado_en": {
            "format": "date-time",
            "type": "string"
          },
          "correo": {
            "type": "string"
          },
          "cuota": {
            "$ref": "#/components/schemas/Cuota"
          },
          "descripcion": {
            "type": "string"
          },
          "direccion": {
            "type": "string"
          },
          "es_negocio": {
            "type": "boolean"
          },
          "horario": {
            "items": {
              "$ref": "#/components/schemas/HorarioComercial"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "jid": {
            "type": "string"
          },
          "opciones": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "propio": {
            "description": "Es el número de la instancia.",
            "type": "boolean"
          },
          "sitios": {
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "zona_horaria": {
            "type": "string"
          }
        },
        "required": [
          "cuota",
          "consultado_en",
          "propio",
          "jid",
          "es_negocio"
        ],
        "type": "object"
      },
      "PerfilV1": {
        "additionalProperties": false,
        "properties": {
          "bloqueados": {
            "description": "Con privacy:read.",
            "format": "int64",
            "type": "integer"
          },
          "bloqueos_en": {
            "format": "date-time",
            "type": "string"
          },
          "consultado_en": {
            "description": "La última consulta al servidor.",
            "format": "date-time",
            "type": "string"
          },
          "foto": {
            "$ref": "#/components/schemas/DatoPerfil"
          },
          "nombre": {
            "$ref": "#/components/schemas/DatoPerfil"
          },
          "privacidad": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Con privacy:read. Opción del SDK → valor (groupadd, last, status, profile, readreceipts, online, calladd, messages, defense, stickers).",
            "type": "object"
          },
          "privacidad_en": {
            "format": "date-time",
            "type": "string"
          },
          "recado": {
            "$ref": "#/components/schemas/DatoPerfil"
          },
          "temporizador_en": {
            "format": "date-time",
            "type": "string"
          },
          "temporizador_por_defecto_seg": {
            "description": "Con privacy:read. El último conocido: el que fijó el motor o el que avisó WhatsApp al cambiarlo en otro dispositivo (el SDK no lo puede consultar).",
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "Permiso": {
        "additionalProperties": false,
        "properties": {
          "expira_en": {
            "format": "date-time",
            "type": "string"
          },
          "url": {
            "description": "GET sin API key mientras no venza. Nunca es público ni permanente.",
            "type": "string"
          }
        },
        "required": [
          "url",
          "expira_en"
        ],
        "type": "object"
      },
      "PoliticaHistorial": {
        "additionalProperties": false,
        "properties": {
          "dias": {
            "description": "Lo más viejo que se importa, en días.",
            "format": "int64",
            "type": "integer"
          },
          "importar": {
            "description": "Si se importan los mensajes del historial (los metadatos y el protocolo se procesan siempre).",
            "type": "boolean"
          },
          "max_mensajes": {
            "description": "La cuota de mensajes de cada trabajo.",
            "format": "int64",
            "type": "integer"
          },
          "medios": {
            "description": "Si se descarga la multimedia de lo importado (si no, quedan sus metadatos).",
            "type": "boolean"
          },
          "propia": {
            "description": "La instancia cambió algo de la política de Ajustes.",
            "type": "boolean"
          }
        },
        "required": [
          "importar",
          "dias",
          "max_mensajes",
          "medios",
          "propia"
        ],
        "type": "object"
      },
      "Pool": {
        "additionalProperties": false,
        "properties": {
          "abiertas": {
            "format": "int64",
            "type": "integer"
          },
          "cerradas_por_vida": {
            "format": "int64",
            "type": "integer"
          },
          "en_uso": {
            "format": "int64",
            "type": "integer"
          },
          "espera_total_ms": {
            "format": "int64",
            "type": "integer"
          },
          "esperas": {
            "format": "int64",
            "type": "integer"
          },
          "max": {
            "format": "int64",
            "type": "integer"
          },
          "ociosas": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "max",
          "abiertas",
          "en_uso",
          "ociosas",
          "esperas",
          "espera_total_ms",
          "cerradas_por_vida"
        ],
        "type": "object"
      },
      "PosicionStream": {
        "additionalProperties": false,
        "properties": {
          "atraso": {
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "type": "string"
          },
          "seq": {
            "description": "El último seq entregado al cliente.",
            "format": "int64",
            "type": "integer"
          },
          "ultimo_seq": {
            "description": "El último seq del ledger que vio el stream.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "instance_id",
          "seq",
          "ultimo_seq",
          "atraso"
        ],
        "type": "object"
      },
      "PresenciasOutputBody": {
        "additionalProperties": false,
        "properties": {
          "suscripciones": {
            "items": {
              "$ref": "#/components/schemas/SuscripcionPresencia"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "suscripciones"
        ],
        "type": "object"
      },
      "Proceso": {
        "additionalProperties": false,
        "properties": {
          "dueno": {
            "description": "Este proceso es el dueño de las sesiones.",
            "type": "boolean"
          },
          "transporte": {
            "type": "boolean"
          }
        },
        "required": [
          "dueno",
          "transporte"
        ],
        "type": "object"
      },
      "ProductoComercial": {
        "additionalProperties": false,
        "properties": {
          "codigo_vendedor": {
            "description": "El retailer_id del negocio; no identifica un producto entre negocios.",
            "type": "string"
          },
          "descripcion": {
            "type": "string"
          },
          "disponibilidad": {
            "description": "Siempre null: el catálogo no informa existencias.",
            "type": [
              "string",
              "null"
            ]
          },
          "escala_precio": {
            "description": "Siempre null: la escala del precio de este IQ no está confirmada.",
            "format": "int64",
            "type": [
              "integer",
              "null"
            ]
          },
          "id": {
            "description": "Opaco y del negocio: no es un identificador global.",
            "type": "string"
          },
          "imagenes": {
            "description": "URLs del proveedor, temporales; el motor no las descarga.",
            "items": {
              "$ref": "#/components/schemas/ImagenProducto"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "moneda": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "oculto": {
            "description": "El atributo is_hidden del servidor; null si no vino (desconocido).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "precio_proveedor": {
            "description": "El precio tal cual lo dio WhatsApp, como texto. Su escala no está confirmada: no es un importe decimal.",
            "type": "string"
          },
          "revision": {
            "description": "El estado de revisión (status_info/status) tal cual: no son existencias.",
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "escala_precio",
          "oculto",
          "disponibilidad",
          "imagenes"
        ],
        "type": "object"
      },
      "ProgresoMedio": {
        "additionalProperties": false,
        "properties": {
          "estado": {
            "enum": [
              "pendiente",
              "ejecutando",
              "listo",
              "fallido",
              "cancelado"
            ],
            "type": "string"
          },
          "intentos": {
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "type": "string"
          },
          "proximo_intento_en": {
            "format": "date-time",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "descarga",
              "importacion",
              "conversion"
            ],
            "type": "string"
          }
        },
        "required": [
          "tipo",
          "estado",
          "intentos"
        ],
        "type": "object"
      },
      "ProveedorV1": {
        "additionalProperties": false,
        "properties": {
          "disponible": {
            "type": "boolean"
          },
          "nombre": {
            "examples": [
              "whatsmeow"
            ],
            "type": "string"
          },
          "version": {
            "type": "string"
          }
        },
        "required": [
          "nombre",
          "disponible",
          "version"
        ],
        "type": "object"
      },
      "ProxiesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "elementos": {
            "items": {
              "$ref": "#/components/schemas/VistaProxy"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "elementos"
        ],
        "type": "object"
      },
      "Prueba": {
        "additionalProperties": false,
        "properties": {
          "duracion_ms": {
            "format": "int64",
            "type": "integer"
          },
          "error": {
            "description": "Código saneado.",
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "status": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "ok",
          "duracion_ms"
        ],
        "type": "object"
      },
      "PublicacionConsultada": {
        "additionalProperties": false,
        "properties": {
          "command_id": {
            "description": "El envío del motor que la publicó.",
            "type": "string"
          },
          "contenido": {
            "description": "Solo cuando se pidió con actualizar=true: lo que devolvió WhatsApp (el tipo y el texto o el caption, como el contenido de message.received)."
          },
          "conteo_en": {
            "format": "date-time",
            "type": "string"
          },
          "direccion": {
            "enum": [
              "entrante",
              "saliente"
            ],
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "provider_id": {
            "description": "El ID de mensaje (el que eligió quien publicó). Distinto del server_id.",
            "type": "string"
          },
          "reaccion_propia": {
            "type": "string"
          },
          "reacciones": {
            "additionalProperties": {
              "format": "int64",
              "type": "integer"
            },
            "description": "Emoji → cantidad (lo último que informó WhatsApp).",
            "type": "object"
          },
          "server_id": {
            "description": "El ID que asignó WhatsApp a la publicación (vistas, reacciones y actualizaciones).",
            "format": "int64",
            "type": "integer"
          },
          "tipo": {
            "type": "string"
          },
          "version": {
            "format": "int64",
            "type": "integer"
          },
          "vistas": {
            "format": "int64",
            "type": "integer"
          },
          "visto": {
            "description": "El motor la marcó como vista.",
            "type": "boolean"
          }
        },
        "required": [
          "server_id",
          "direccion",
          "tipo",
          "momento",
          "vistas",
          "reacciones",
          "visto",
          "version"
        ],
        "type": "object"
      },
      "PublicacionesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "next_antes": {
            "description": "El server_id para pedir la página siguiente (más vieja). Con actualizar=true y la página remota llena (tantas como cantidad), has_more es true: puede haber más en WhatsApp.",
            "format": "int64",
            "type": "integer"
          },
          "publicaciones": {
            "items": {
              "$ref": "#/components/schemas/PublicacionConsultada"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "publicaciones",
          "has_more"
        ],
        "type": "object"
      },
      "ReciboDestinatario": {
        "additionalProperties": false,
        "properties": {
          "destinatario": {
            "$ref": "#/components/schemas/Peer"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "entregado",
              "leido",
              "reproducido"
            ],
            "type": "string"
          }
        },
        "required": [
          "destinatario",
          "tipo",
          "momento"
        ],
        "type": "object"
      },
      "ReciboVista": {
        "additionalProperties": false,
        "properties": {
          "destinatario": {
            "$ref": "#/components/schemas/Peer"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "tipo": {
            "description": "entregado, leido, reproducido…",
            "type": "string"
          }
        },
        "required": [
          "destinatario",
          "tipo",
          "momento"
        ],
        "type": "object"
      },
      "RecibosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "recibos": {
            "items": {
              "$ref": "#/components/schemas/ReciboDestinatario"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "recibos"
        ],
        "type": "object"
      },
      "Reconexiones": {
        "additionalProperties": false,
        "properties": {
          "automatica": {
            "type": "boolean"
          },
          "bloqueada_hasta": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "desconexiones_24h": {
            "format": "int64",
            "type": "integer"
          },
          "proximo_intento_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "reintentos": {
            "description": "Intentos seguidos del conciliador.",
            "format": "int64",
            "type": "integer"
          },
          "reintentos_proceso": {
            "description": "Reintentos del conciliador desde que arrancó este proceso.",
            "format": "int64",
            "type": "integer"
          },
          "total": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "total",
          "desconexiones_24h",
          "reintentos",
          "proximo_intento_en",
          "automatica",
          "bloqueada_hasta",
          "reintentos_proceso"
        ],
        "type": "object"
      },
      "RefMensajeInteractivo": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "description": "El autor del mensaje citado, si el contexto lo informa (en un grupo): para correlacionar tiene que ser el número de esta instancia.",
            "type": "string"
          },
          "command_id": {
            "description": "El comando que lo mandó (solo si se correlacionó).",
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          }
        },
        "required": [
          "provider_id"
        ],
        "type": "object"
      },
      "Referencia": {
        "additionalProperties": false,
        "properties": {
          "autor": {
            "type": "string"
          },
          "citado_vencido": {
            "type": "boolean"
          },
          "de_mi": {
            "type": "boolean"
          },
          "provider_id": {
            "type": "string"
          }
        },
        "required": [
          "provider_id",
          "de_mi"
        ],
        "type": "object"
      },
      "Replay": {
        "additionalProperties": false,
        "properties": {
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "entregas": {
            "description": "Entregas nuevas creadas (de los mismos hechos).",
            "format": "int64",
            "type": "integer"
          },
          "replay_id": {
            "type": "string"
          },
          "suscripcion_id": {
            "type": "string"
          }
        },
        "required": [
          "replay_id",
          "suscripcion_id",
          "entregas",
          "creado_en"
        ],
        "type": "object"
      },
      "Responder-passkeyRequest": {
        "additionalProperties": false,
        "properties": {
          "generacion": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          },
          "respuesta": {
            "additionalProperties": {},
            "description": "PublicKeyCredential serializado (id, rawId, type, response).",
            "type": "object"
          }
        },
        "required": [
          "generacion",
          "respuesta"
        ],
        "type": "object"
      },
      "RespuestaVista": {
        "additionalProperties": false,
        "properties": {
          "accion": {
            "$ref": "#/components/schemas/AccionRespondida"
          },
          "autor": {
            "$ref": "#/components/schemas/Peer"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "correlacion": {
            "enum": [
              "correlacionada",
              "accion_desconocida",
              "sin_mensaje",
              "otro_chat",
              "otro_autor",
              "no_respondible",
              "desconocida"
            ],
            "type": "string"
          },
          "crudo": {
            "description": "interactive.unknown: lo que llegó, saneado y acotado (sin el mensaje citado)."
          },
          "event_id": {
            "type": "string"
          },
          "formato": {
            "description": "texto: el número de una opción del respaldo de una lista (respaldo_texto).",
            "enum": [
              "buttons_response",
              "list_response",
              "template_button_reply",
              "native_flow",
              "texto",
              "desconocida"
            ],
            "type": "string"
          },
          "from_me": {
            "type": "boolean"
          },
          "mensaje": {
            "$ref": "#/components/schemas/RefMensajeInteractivo"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "motivo": {
            "description": "interactive.unknown: formato_desconocido, flujo_desconocido, sin_id, id_invalido, contexto_invalido o parametros_invalidos.",
            "type": "string"
          },
          "nombre_flujo": {
            "type": "string"
          },
          "parametros": {
            "additionalProperties": {},
            "description": "Los de una respuesta de native flow: un objeto JSON acotado y saneado.",
            "type": "object"
          },
          "provider_id": {
            "type": "string"
          },
          "response_id": {
            "type": "string"
          },
          "via": {
            "description": "texto: la fila se eligió contestando su número al respaldo de texto de la lista (no por la lista).",
            "enum": [
              "texto",
              ""
            ],
            "type": "string"
          }
        },
        "required": [
          "response_id",
          "event_id",
          "chat",
          "autor",
          "provider_id",
          "from_me",
          "formato",
          "accion",
          "correlacion",
          "momento"
        ],
        "type": "object"
      },
      "RespuestasOutputBody": {
        "additionalProperties": false,
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": "string"
          },
          "respuestas": {
            "items": {
              "$ref": "#/components/schemas/RespuestaVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "respuestas",
          "has_more"
        ],
        "type": "object"
      },
      "ResultadoEncuesta": {
        "additionalProperties": false,
        "properties": {
          "conocida": {
            "description": "false: llegaron votos de una encuesta que el motor no vio crear (solo se cuentan los votantes).",
            "type": "boolean"
          },
          "opciones": {
            "items": {
              "$ref": "#/components/schemas/OpcionResultado"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "pregunta": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "seleccionables": {
            "format": "int64",
            "type": "integer"
          },
          "sin_descifrar": {
            "description": "Votos que no se pudieron descifrar (sin el secreto): nunca se inventa una opción.",
            "format": "int64",
            "type": "integer"
          },
          "votantes": {
            "description": "Quienes tienen un voto vigente (también vacío: quitaron su voto).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "provider_id",
          "conocida",
          "seleccionables",
          "opciones",
          "votantes",
          "sin_descifrar"
        ],
        "type": "object"
      },
      "ResultadoNumero": {
        "additionalProperties": false,
        "properties": {
          "jid": {
            "description": "Su identidad canónica según el servidor (puede ser un LID).",
            "type": "string"
          },
          "lid": {
            "type": "string"
          },
          "negocio": {
            "description": "Es una cuenta de WhatsApp Business verificada.",
            "type": "boolean"
          },
          "nombre_verificado": {
            "type": "string"
          },
          "peer_ref": {
            "description": "Si la instancia ya lo conocía: su peer estable.",
            "type": "string"
          },
          "pn": {
            "description": "El JID de su teléfono.",
            "type": "string"
          },
          "registrado": {
            "description": "Si tiene una cuenta de WhatsApp.",
            "type": "boolean"
          },
          "telefono": {
            "description": "El número consultado (internacional, con +).",
            "type": "string"
          }
        },
        "required": [
          "telefono",
          "registrado"
        ],
        "type": "object"
      },
      "ResumenLotes": {
        "additionalProperties": false,
        "properties": {
          "importados": {
            "format": "int64",
            "type": "integer"
          },
          "omitidos": {
            "description": "De un trabajo que ya había terminado (cancelado, cuota).",
            "format": "int64",
            "type": "integer"
          },
          "pendientes": {
            "description": "Con contenido por importar.",
            "format": "int64",
            "type": "integer"
          },
          "recibidos": {
            "format": "int64",
            "type": "integer"
          },
          "sin_contenido": {
            "description": "Solo metadatos y protocolo (la importación estaba apagada o el lote no era de un trabajo).",
            "format": "int64",
            "type": "integer"
          },
          "ultimo_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "recibidos",
          "sin_contenido",
          "pendientes",
          "importados",
          "omitidos"
        ],
        "type": "object"
      },
      "RetoVista": {
        "additionalProperties": false,
        "properties": {
          "expira_en": {
            "format": "date-time",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "qr",
              "codigo",
              "passkey",
              "passkey_confirmacion"
            ],
            "type": "string"
          },
          "valor": {
            "type": "string"
          }
        },
        "required": [
          "tipo",
          "valor",
          "expira_en"
        ],
        "type": "object"
      },
      "Seccion": {
        "additionalProperties": false,
        "properties": {
          "filas": {
            "items": {
              "$ref": "#/components/schemas/Fila"
            },
            "maxItems": 10,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          },
          "titulo": {
            "description": "Obligatorio si hay más de una sección.",
            "maxLength": 24,
            "type": "string"
          }
        },
        "required": [
          "filas"
        ],
        "type": "object"
      },
      "SecretoEmitido": {
        "additionalProperties": false,
        "properties": {
          "key_id": {
            "type": "string"
          },
          "valor": {
            "description": "Guárdalo sellado en tu app: no se vuelve a mostrar.",
            "type": "string"
          }
        },
        "required": [
          "key_id",
          "valor"
        ],
        "type": "object"
      },
      "SeguimientoInteractivo": {
        "additionalProperties": false,
        "properties": {
          "acciones": {
            "items": {
              "$ref": "#/components/schemas/AccionInteractiva"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "aceptacion": {
            "enum": [
              "pendiente",
              "aceptado",
              "rechazado",
              "no_salio",
              "desconocido"
            ],
            "type": "string"
          },
          "aviso": {
            "description": "Siempre: no garantizado en números no oficiales.",
            "type": "string"
          },
          "chat": {
            "$ref": "#/components/schemas/Peer"
          },
          "command_id": {
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "error_code": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "recibo": {
            "enum": [
              "no_observado",
              "entregado",
              "leido"
            ],
            "type": "string"
          },
          "render": {
            "enum": [
              "desconocido"
            ],
            "type": "string"
          },
          "respuesta": {
            "enum": [
              "no_observada",
              "observada",
              "no_observable"
            ],
            "type": "string"
          },
          "respuestas": {
            "description": "Los event_id de sus interactive.response.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "variante": {
            "enum": [
              "buttons",
              "list",
              "carousel"
            ],
            "type": "string"
          },
          "version": {
            "description": "La estrategia del builder con la que salió.",
            "type": "string"
          }
        },
        "required": [
          "provider_id",
          "command_id",
          "chat",
          "variante",
          "version",
          "aviso",
          "aceptacion",
          "recibo",
          "render",
          "respuesta",
          "respuestas",
          "acciones",
          "created_at"
        ],
        "type": "object"
      },
      "Seguir-canalRequest": {
        "additionalProperties": false,
        "properties": {
          "canal": {
            "$ref": "#/components/schemas/CanalRef"
          }
        },
        "required": [
          "canal"
        ],
        "type": "object"
      },
      "SesionViva": {
        "additionalProperties": false,
        "properties": {
          "abierta": {
            "type": "boolean"
          },
          "autenticada": {
            "type": "boolean"
          },
          "conectada": {
            "type": "boolean"
          }
        },
        "required": [
          "abierta",
          "conectada",
          "autenticada"
        ],
        "type": "object"
      },
      "SincronizacionContactosOutputBody": {
        "additionalProperties": false,
        "properties": {
          "cambiados": {
            "description": "Cuántos contactos cambiaron.",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "cambiados"
        ],
        "type": "object"
      },
      "SolicitudVista": {
        "additionalProperties": false,
        "properties": {
          "jid": {
            "type": "string"
          },
          "momento": {
            "format": "date-time",
            "type": "string"
          },
          "telefono": {
            "type": "string"
          }
        },
        "required": [
          "jid",
          "momento"
        ],
        "type": "object"
      },
      "SolicitudesOutputBody": {
        "additionalProperties": false,
        "properties": {
          "solicitudes": {
            "items": {
              "$ref": "#/components/schemas/SolicitudVista"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "solicitudes"
        ],
        "type": "object"
      },
      "StreamAbierto": {
        "additionalProperties": false,
        "properties": {
          "abierto_en": {
            "format": "date-time",
            "type": "string"
          },
          "atraso": {
            "description": "Eventos del ledger que el cliente todavía no recibió.",
            "format": "int64",
            "type": "integer"
          },
          "buffer_bytes": {
            "description": "Lo que espera al cliente en memoria.",
            "format": "int64",
            "type": "integer"
          },
          "buffer_limite": {
            "format": "int64",
            "type": "integer"
          },
          "bytes_enviados": {
            "format": "int64",
            "type": "integer"
          },
          "cliente_id": {
            "type": "string"
          },
          "cliente_nombre": {
            "type": "string"
          },
          "estado": {
            "description": "lento: el buffer está por encima de la mitad.",
            "enum": [
              "al_dia",
              "atrasado",
              "lento"
            ],
            "type": "string"
          },
          "eventos_enviados": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "instancias": {
            "items": {
              "$ref": "#/components/schemas/PosicionStream"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "instancias_filtro": {
            "description": "Vacío: todas las que alcanza la key.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "key_prefijo": {
            "type": "string"
          },
          "tipos": {
            "description": "Vacío: todos.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "transporte": {
            "enum": [
              "sse",
              "websocket"
            ],
            "type": "string"
          },
          "ultimo_envio_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "cliente_id",
          "cliente_nombre",
          "key_prefijo",
          "transporte",
          "tipos",
          "instancias_filtro",
          "abierto_en",
          "eventos_enviados",
          "bytes_enviados",
          "buffer_bytes",
          "buffer_limite",
          "atraso",
          "estado",
          "instancias"
        ],
        "type": "object"
      },
      "StreamCerrado": {
        "additionalProperties": false,
        "properties": {
          "abierto_en": {
            "format": "date-time",
            "type": "string"
          },
          "cerrado_en": {
            "format": "date-time",
            "type": "string"
          },
          "cliente_id": {
            "type": "string"
          },
          "cliente_nombre": {
            "type": "string"
          },
          "eventos_enviados": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "key_prefijo": {
            "type": "string"
          },
          "motivo": {
            "enum": [
              "credencial_revocada",
              "sin_scope",
              "cliente_lento",
              "apagado",
              "cortado_por_operador",
              "desconectado",
              "error_interno"
            ],
            "type": "string"
          },
          "transporte": {
            "enum": [
              "sse",
              "websocket"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "cliente_id",
          "cliente_nombre",
          "key_prefijo",
          "transporte",
          "motivo",
          "abierto_en",
          "cerrado_en",
          "eventos_enviados"
        ],
        "type": "object"
      },
      "StreamsOutputBody": {
        "additionalProperties": false,
        "properties": {
          "abiertos": {
            "items": {
              "$ref": "#/components/schemas/StreamAbierto"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "cierres": {
            "description": "Los últimos cierres, del más nuevo al más viejo.",
            "items": {
              "$ref": "#/components/schemas/StreamCerrado"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "abiertos",
          "cierres"
        ],
        "type": "object"
      },
      "SubgrupoVista": {
        "additionalProperties": false,
        "properties": {
          "anuncios": {
            "description": "El grupo de anuncios de la comunidad (lo crea WhatsApp).",
            "type": "boolean"
          },
          "cambio_en": {
            "format": "date-time",
            "type": "string"
          },
          "conocido": {
            "description": "El número está en ese grupo y el motor tiene su ficha.",
            "type": "boolean"
          },
          "desde": {
            "enum": [
              "whatsapp",
              "motor",
              "consulta"
            ],
            "type": "string"
          },
          "grupo": {
            "$ref": "#/components/schemas/Peer"
          },
          "nombre": {
            "type": "string"
          },
          "rol_propio": {
            "type": "string"
          },
          "version": {
            "description": "La versión de la relación (sube con cada vínculo o desvínculo).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "grupo",
          "nombre",
          "anuncios",
          "conocido",
          "version",
          "cambio_en",
          "desde"
        ],
        "type": "object"
      },
      "SuscripcionCreada": {
        "additionalProperties": false,
        "properties": {
          "secreto": {
            "$ref": "#/components/schemas/SecretoEmitido"
          },
          "suscripcion": {
            "$ref": "#/components/schemas/Vista"
          }
        },
        "required": [
          "suscripcion",
          "secreto"
        ],
        "type": "object"
      },
      "SuscripcionPresencia": {
        "additionalProperties": false,
        "properties": {
          "contacto": {
            "$ref": "#/components/schemas/Peer"
          },
          "creada_en": {
            "format": "date-time",
            "type": "string"
          },
          "disponible": {
            "description": "La última presencia que llegó mientras estaba vigente (vacío: ninguna o ya venció).",
            "type": "boolean"
          },
          "estado_chat": {
            "type": "string"
          },
          "ultima_vez": {
            "format": "date-time",
            "type": "string"
          },
          "vence_en": {
            "format": "date-time",
            "type": "string"
          },
          "vigente": {
            "description": "false: pasó su TTL (ya no llegan eventos presence de ese contacto).",
            "type": "boolean"
          },
          "vista_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "contacto",
          "creada_en",
          "vence_en",
          "vigente"
        ],
        "type": "object"
      },
      "Tarjeta": {
        "additionalProperties": false,
        "properties": {
          "botones": {
            "description": "De 1 a 2: reply, copy, url o call (pix no va en un carrusel).",
            "items": {
              "$ref": "#/components/schemas/Boton"
            },
            "maxItems": 2,
            "minItems": 1,
            "type": [
              "array",
              "null"
            ]
          },
          "cuerpo": {
            "maxLength": 160,
            "minLength": 1,
            "type": "string"
          },
          "medio": {
            "$ref": "#/components/schemas/MedioTarjeta"
          },
          "pie": {
            "maxLength": 60,
            "type": "string"
          }
        },
        "required": [
          "cuerpo",
          "botones"
        ],
        "type": "object"
      },
      "TemporizadorPorDefecto": {
        "additionalProperties": false,
        "properties": {
          "segundos": {
            "description": "0 (desactivado), 86400 (24 horas), 604800 (7 días) o 7776000 (90 días).",
            "format": "int64",
            "maximum": 7776000,
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "segundos"
        ],
        "type": "object"
      },
      "TrabajoSync": {
        "additionalProperties": false,
        "properties": {
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "aviso": {
            "type": "string"
          },
          "cantidad": {
            "description": "Mensajes por pedido.",
            "format": "int64",
            "type": "integer"
          },
          "chat_actual": {
            "format": "int64",
            "type": "integer"
          },
          "chats": {
            "description": "Los peer_ref de los chats del trabajo (vacío en el inicial).",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "command_id": {
            "type": "string"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "desde": {
            "description": "El corte: nada anterior se importa.",
            "format": "date-time",
            "type": "string"
          },
          "duplicados": {
            "description": "Mensajes que el motor ya tenía (en vivo o de otro lote): no se duplican.",
            "format": "int64",
            "type": "integer"
          },
          "estado": {
            "description": "esperando: un pedido al teléfono sin respuesta todavía; en_pausa: contrapresión de las entregas.",
            "enum": [
              "en_curso",
              "esperando",
              "en_pausa",
              "completado",
              "cancelado",
              "fallido"
            ],
            "type": "string"
          },
          "id": {
            "description": "El mismo ID que el comando que lo creó (command_id).",
            "type": "string"
          },
          "importados": {
            "description": "Mensajes nuevos para el motor.",
            "format": "int64",
            "type": "integer"
          },
          "instance_id": {
            "type": "string"
          },
          "lotes_importados": {
            "format": "int64",
            "type": "integer"
          },
          "lotes_recibidos": {
            "format": "int64",
            "type": "integer"
          },
          "mas_nuevo_en": {
            "format": "date-time",
            "type": "string"
          },
          "mas_viejo_en": {
            "description": "El mensaje más viejo importado.",
            "format": "date-time",
            "type": "string"
          },
          "max_mensajes": {
            "description": "La cuota del trabajo.",
            "format": "int64",
            "type": "integer"
          },
          "mensajes_vistos": {
            "description": "Lo que trajeron los lotes (también lo omitido).",
            "format": "int64",
            "type": "integer"
          },
          "motivo": {
            "description": "Por qué está en pausa o por qué terminó: contrapresion, cuota, corte, sin_mas_historial, sin_mas_lotes, chats_recorridos, pedido_atendido, sin_respuesta (el teléfono no contestó: sin conexión o, según WhatsApp Web, sin nada más viejo de ese chat), sin_mensajes, fuera_del_historial (el chat no vino en el historial inicial de este vínculo con mensajes que queden en el teléfono, por ejemplo porque empezó después: WhatsApp Web no lo pide), solo_en_el_telefono, pedido_rechazado, cancelado.",
            "type": "string"
          },
          "no_soportados": {
            "description": "Avisos del sistema o protocolo: se cuentan, no se inventan.",
            "format": "int64",
            "type": "integer"
          },
          "omitidos_cuota": {
            "description": "Fuera de la cuota.",
            "format": "int64",
            "type": "integer"
          },
          "omitidos_fecha": {
            "description": "Anteriores al corte.",
            "format": "int64",
            "type": "integer"
          },
          "pedido_vence_en": {
            "description": "Hasta cuándo se espera la respuesta del teléfono.",
            "format": "date-time",
            "type": "string"
          },
          "pedidos": {
            "description": "Pedidos que salieron al teléfono.",
            "format": "int64",
            "type": "integer"
          },
          "progreso": {
            "description": "El progreso (0-100) que informó WhatsApp en el último lote. No es la historia completa.",
            "format": "int64",
            "type": "integer"
          },
          "sin_respuesta": {
            "description": "Pedidos que el teléfono no contestó a tiempo.",
            "format": "int64",
            "type": "integer"
          },
          "terminado_en": {
            "format": "date-time",
            "type": "string"
          },
          "tipo": {
            "enum": [
              "inicial",
              "pedido",
              "importacion"
            ],
            "type": "string"
          },
          "ultimo_lote_en": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "instance_id",
          "tipo",
          "estado",
          "chats",
          "chat_actual",
          "cantidad",
          "max_mensajes",
          "pedidos",
          "sin_respuesta",
          "lotes_recibidos",
          "lotes_importados",
          "mensajes_vistos",
          "importados",
          "duplicados",
          "omitidos_fecha",
          "omitidos_cuota",
          "no_soportados",
          "creado_en",
          "actualizado_en",
          "aviso"
        ],
        "type": "object"
      },
      "Ubicacion": {
        "additionalProperties": false,
        "properties": {
          "direccion": {
            "maxLength": 300,
            "type": "string"
          },
          "latitud": {
            "format": "double",
            "maximum": 90,
            "minimum": -90,
            "type": "number"
          },
          "longitud": {
            "format": "double",
            "maximum": 180,
            "minimum": -180,
            "type": "number"
          },
          "nombre": {
            "maxLength": 200,
            "type": "string"
          }
        },
        "required": [
          "latitud",
          "longitud"
        ],
        "type": "object"
      },
      "UltimoEvento": {
        "additionalProperties": false,
        "properties": {
          "lag_ms": {
            "format": "int64",
            "type": "integer"
          },
          "occurred_at": {
            "format": "date-time",
            "type": "string"
          },
          "received_at": {
            "format": "date-time",
            "type": "string"
          },
          "seq": {
            "format": "int64",
            "type": "integer"
          },
          "tipo": {
            "type": "string"
          }
        },
        "required": [
          "seq",
          "tipo",
          "occurred_at",
          "received_at",
          "lag_ms"
        ],
        "type": "object"
      },
      "UsoComercio": {
        "additionalProperties": false,
        "properties": {
          "cantidad": {
            "format": "int64",
            "type": "integer"
          },
          "tipo": {
            "enum": [
              "catalogo",
              "colecciones"
            ],
            "type": "string"
          }
        },
        "required": [
          "tipo",
          "cantidad"
        ],
        "type": "object"
      },
      "UsoConsultas": {
        "additionalProperties": false,
        "properties": {
          "cantidad": {
            "format": "int64",
            "type": "integer"
          },
          "tipo": {
            "enum": [
              "numeros",
              "perfiles",
              "foto",
              "perfil_comercial"
            ],
            "type": "string"
          }
        },
        "required": [
          "tipo",
          "cantidad"
        ],
        "type": "object"
      },
      "Vista": {
        "additionalProperties": false,
        "properties": {
          "actualizada_en": {
            "format": "date-time",
            "type": "string"
          },
          "claves": {
            "items": {
              "$ref": "#/components/schemas/VistaClave"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "cliente_id": {
            "type": "string"
          },
          "creada_en": {
            "format": "date-time",
            "type": "string"
          },
          "estado": {
            "enum": [
              "activa",
              "pausada",
              "suspendida",
              "eliminada"
            ],
            "type": "string"
          },
          "fallidas": {
            "format": "int64",
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "instancias": {
            "description": "Vacío: todas las instancias de la app.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "motivo": {
            "description": "Por qué está suspendida (p. ej. rechazo_401).",
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "ordenado": {
            "description": "Los eventos de una instancia salen en orden de seq: el siguiente espera al anterior.",
            "type": "boolean"
          },
          "pendientes": {
            "format": "int64",
            "type": "integer"
          },
          "suspendida_en": {
            "format": "date-time",
            "type": "string"
          },
          "tipos": {
            "description": "Vacío: todos los tipos.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "url": {
            "type": "string"
          },
          "version": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "cliente_id",
          "nombre",
          "url",
          "instancias",
          "tipos",
          "ordenado",
          "estado",
          "version",
          "claves",
          "pendientes",
          "fallidas",
          "creada_en",
          "actualizada_en"
        ],
        "type": "object"
      },
      "VistaClave": {
        "additionalProperties": false,
        "properties": {
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "key_id": {
            "type": "string"
          },
          "vence_en": {
            "description": "Fin de la ventana de rotación (null: la vigente).",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "key_id",
          "creado_en",
          "vence_en"
        ],
        "type": "object"
      },
      "VistaEntrega": {
        "additionalProperties": false,
        "properties": {
          "creada_en": {
            "format": "date-time",
            "type": "string"
          },
          "delivery_id": {
            "type": "string"
          },
          "entregada_en": {
            "format": "date-time",
            "type": "string"
          },
          "estado": {
            "enum": [
              "pendiente",
              "entregada",
              "fallida"
            ],
            "type": "string"
          },
          "event_id": {
            "type": "string"
          },
          "fallida_en": {
            "format": "date-time",
            "type": "string"
          },
          "instance_id": {
            "type": "string"
          },
          "instancia": {
            "description": "Nombre de la instancia.",
            "type": "string"
          },
          "intentos": {
            "format": "int64",
            "type": "integer"
          },
          "intentos_detalle": {
            "items": {
              "$ref": "#/components/schemas/VistaIntento"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "proximo_intento_en": {
            "format": "date-time",
            "type": "string"
          },
          "replay_id": {
            "type": "string"
          },
          "seq": {
            "format": "int64",
            "type": "integer"
          },
          "suscripcion": {
            "description": "Nombre de la suscripción.",
            "type": "string"
          },
          "suscripcion_id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "ultimo_error": {
            "description": "Error saneado: un código, nunca la URL ni un cuerpo.",
            "type": "string"
          },
          "ultimo_status": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "delivery_id",
          "suscripcion_id",
          "suscripcion",
          "instance_id",
          "instancia",
          "event_id",
          "seq",
          "type",
          "estado",
          "intentos",
          "creada_en"
        ],
        "type": "object"
      },
      "VistaIntento": {
        "additionalProperties": false,
        "properties": {
          "duracion_ms": {
            "format": "int64",
            "type": "integer"
          },
          "error": {
            "type": "string"
          },
          "iniciado_en": {
            "format": "date-time",
            "type": "string"
          },
          "key_ids": {
            "type": "string"
          },
          "numero": {
            "format": "int64",
            "type": "integer"
          },
          "status": {
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "numero",
          "iniciado_en",
          "duracion_ms",
          "key_ids"
        ],
        "type": "object"
      },
      "VistaPrevia": {
        "additionalProperties": false,
        "properties": {
          "descripcion": {
            "maxLength": 1000,
            "type": "string"
          },
          "miniatura_media_id": {
            "description": "Una imagen subida a esta instancia (POST /v1/instances/{id}/media/uploads), lista.",
            "type": "string"
          },
          "obtener": {
            "description": "Que el motor lea el título y la descripción de la página (solo si su host está en los destinos permitidos; si falla, sale sin ellos).",
            "type": "boolean"
          },
          "titulo": {
            "maxLength": 300,
            "type": "string"
          },
          "url": {
            "description": "El enlace, tal como aparece en el texto.",
            "maxLength": 2000,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "VistaProxy": {
        "additionalProperties": false,
        "properties": {
          "actualizado_en": {
            "format": "date-time",
            "type": "string"
          },
          "con_credencial": {
            "description": "Tiene usuario y contraseña (sellados; nunca se muestran).",
            "type": "boolean"
          },
          "creado_en": {
            "format": "date-time",
            "type": "string"
          },
          "esquema": {
            "enum": [
              "http",
              "https",
              "socks5"
            ],
            "type": "string"
          },
          "estado": {
            "enum": [
              "sin_probar",
              "conectado",
              "caido"
            ],
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "instancias": {
            "description": "Instancias que lo usan.",
            "format": "int64",
            "type": "integer"
          },
          "nombre": {
            "type": "string"
          },
          "probado_en": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "puerto": {
            "format": "int64",
            "type": "integer"
          },
          "ultimo_error": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "nombre",
          "esquema",
          "host",
          "puerto",
          "con_credencial",
          "estado",
          "ultimo_error",
          "probado_en",
          "instancias",
          "creado_en",
          "actualizado_en"
        ],
        "type": "object"
      },
      "WhoamiCliente": {
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "nombre"
        ],
        "type": "object"
      },
      "WhoamiKey": {
        "additionalProperties": false,
        "properties": {
          "entorno": {
            "examples": [
              "live"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "instancias": {
            "description": "Vacía: todas las instancias de la app.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "prefijo": {
            "type": "string"
          },
          "scopes": {
            "examples": [
              [
                "messages:send",
                "messages:read",
                "events:read"
              ]
            ],
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "prefijo",
          "entorno",
          "scopes",
          "instancias"
        ],
        "type": "object"
      },
      "WhoamiOutputBody": {
        "additionalProperties": false,
        "properties": {
          "cliente": {
            "$ref": "#/components/schemas/WhoamiCliente"
          },
          "key": {
            "$ref": "#/components/schemas/WhoamiKey"
          }
        },
        "required": [
          "cliente",
          "key"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "bearerFormat": "mw_live_<id>_<secreto>",
        "description": "API key de una app cliente.",
        "scheme": "bearer",
        "type": "http"
      },
      "permisoMedia": {
        "description": "Permiso temporal de descarga de un medio (de `GET /v1/media/{id}`): vale sin API key hasta que vence.",
        "in": "query",
        "name": "permiso",
        "type": "apiKey"
      }
    }
  }
}
