# Catálogo de eventos

> Generado desde `openapi/openapi.yaml` (sección `webhooks`). `pnpm docs:gen`.

Todos los eventos llevan este sobre; `data` cambia según el tipo.

```json
{
  "id": "evt_018f3c5a9b2d7e4f8a1b2c3d4e5f6a7b",
  "type": "whatsapp.message.received",
  "tenant_id": "ten_…",
  "tenant_ref": "CLI-0042",
  "occurred_at": "2026-10-12T09:41:07Z",
  "data": {}
}
```

| Evento | Cuándo se emite | Campos de `data` |
| --- | --- | --- |
| `whatsapp.message.received` | Un contacto escribe. Es el evento principal para bots e integraciones de entrada. | `conversation_id`: string (`cnv_…`)<br>`contact`: [ContactSummary](#contactsummary)<br>`message`: [Message](#message) |
| `whatsapp.message.sent_from_app` | Una persona escribe desde la app del móvil | `conversation_id`: string (`cnv_…`)<br>`contact`: [ContactSummary](#contactsummary)<br>`message`: [Message](#message) |
| `whatsapp.message.status` | Un envío pasa a `sent`, `delivered`, `read` o `failed` (con `error`). Incluye `billable` y `pricing_category` cuando Meta los informa. | `message`: [Message](#message)<br>`status`: [MessageStatus](#messagestatus)<br>`error`: [MessageError](#messageerror) \| null |
| `whatsapp.conversation.assigned` | Se asigna o reasigna una conversación. | `conversation`: [Conversation](#conversation)<br>`previous_agent_id`: string (`agt_…`) \| null |
| `whatsapp.conversation.closed` | Se cierra una conversación. | `conversation`: [Conversation](#conversation)<br>`previous_agent_id`: string (`agt_…`) \| null |
| `whatsapp.conversation.reopened` | Se reabre (normalmente porque el contacto vuelve a escribir). | `conversation`: [Conversation](#conversation)<br>`previous_agent_id`: string (`agt_…`) \| null |
| `whatsapp.template.status_changed` | Meta aprueba, rechaza, pausa o desactiva una plantilla. `previous.status` trae el estado anterior. | `template`: [Template](#template)<br>`previous`: object |
| `whatsapp.template.quality_changed` | Meta cambia la calidad de una plantilla. | `template`: [Template](#template)<br>`previous`: object |
| `whatsapp.template.category_changed` | Meta cambia la categoría (puede cambiar el coste de los envíos). | `template`: [Template](#template)<br>`previous`: object |
| `whatsapp.number.connected` | Termina el alta de un número. | `number`: [Number](#number)<br>`reason`: string \| null<br>`initiated_by`: `USER` \| `SYSTEM` \| `null` |
| `whatsapp.number.updated` | Cambia la calidad, el límite de mensajería o el estado de un número. | `number`: [Number](#number)<br>`reason`: string \| null<br>`initiated_by`: `USER` \| `SYSTEM` \| `null` |
| `whatsapp.number.disconnected` | Se desconecta un número. | `number`: [Number](#number)<br>`reason`: string \| null<br>`initiated_by`: `USER` \| `SYSTEM` \| `null` |
| `whatsapp.account.payment_blocked` | La cuenta queda bloqueada por pago en Meta. | `account`: [WhatsAppAccount](#whatsappaccount)<br>`reason`: string \| null |
| `whatsapp.account.payment_active` | La cuenta confirma el pago (tras el primer envío de plantilla aceptado) o se desbloquea. | `account`: [WhatsAppAccount](#whatsappaccount)<br>`reason`: string \| null |
| `whatsapp.account.restricted` | Meta restringe la cuenta, o el token del cliente deja de ser válido (`reason: credential_invalid`: hay que repetir el alta). | `account`: [WhatsAppAccount](#whatsappaccount)<br>`reason`: string \| null |
| `whatsapp.signup.failed` | Falla un alta de número; trae el paso y el error. | `session_id`: string (`sus_…`)<br>`step`: [SignupStep](#signupstep)<br>`error`: object |
| `whatsapp.usage.alert` | El gasto del mes llega al 80 % o al 100 % del importe fijado por el tenant. | `threshold_pct`: `80` \| `100`<br>`spent`: number<br>`limit`: number<br>`currency`: string |
| `license.updated` | Cambia el estado o los límites de la licencia. | `license`: [License](#license) |

`whatsapp.test` se emite solo con `POST /v1/webhook-subscriptions/{id}/test`.

Comodines al suscribirse: `*`, `whatsapp.*`, `whatsapp.message.*`.
