Skip to main content
Todo webhook entregado por Waspy comparte el mismo envelope:
{
  "event": "message.received",
  "webhookId": "uuid-de-tu-suscripcion",
  "deliveredAt": "2026-04-19T12:34:56.789Z",
  "attempt": 1,
  "data": { /* específico del evento — ver abajo */ }
}
Headers HTTP en cada delivery:
Content-Type: application/json
User-Agent: Waspy-Webhooks/1.0
X-Waspy-Signature: t=1745067296,v1=<hmac-hex>
X-Waspy-Webhook-Id: <uuid>
X-Waspy-Webhook-Event: message.received
X-Waspy-Webhook-Version: v1
X-Waspy-Webhook-Attempt: 1

message.received

Llega cada vez que un contacto te envía un mensaje (texto, media, ubicación, etc).
{
  "event": "message.received",
  "webhookId": "...",
  "deliveredAt": "2026-04-19T12:34:56.789Z",
  "attempt": 1,
  "data": {
    "id": "uuid-mensaje-waspy",
    "conversationId": "uuid-conversacion",
    "contactId": "uuid-contacto",
    "phoneNumberId": "uuid-canal",
    "direction": "inbound",
    "type": "text",
    "content": { "body": "Hola, tienen stock?" },
    "status": "delivered",
    "waMessageId": "wamid.HBgL...",
    "errorCode": null,
    "errorMessage": null,
    "origin": "inbound",
    "sentByAi": false,
    "campaignId": null,
    "mediaId": null,
    "mediaKey": null,
    "createdAt": "2026-04-19T12:34:55.000Z",
    "contact": {
      "id": "uuid-contacto",
      "name": "María Pérez",
      "phoneNumber": "+5491126032641"
    }
  }
}
Para mensajes con media (imagen, audio, video, documento), mediaId y mediaKey se completan cuando termina la descarga interna desde Meta. Resolvé mediaId a una URL firmada con GET /media/:id. Ver Media.

message.status_changed

Llega cuando cambia el estado de un mensaje saliente que vos enviaste.
{
  "event": "message.status_changed",
  "webhookId": "...",
  "deliveredAt": "2026-04-19T12:36:01.000Z",
  "attempt": 1,
  "data": {
    "id": "uuid-mensaje",
    "conversationId": "uuid-conversacion",
    "contactId": "uuid-contacto",
    "phoneNumberId": "uuid-canal",
    "direction": "outbound",
    "type": "text",
    "content": { "body": "Tu pedido #1847 fue despachado." },
    "status": "delivered",
    "waMessageId": "wamid.OUT...",
    "errorCode": null,
    "errorMessage": null,
    "origin": "external_api",
    "sentByAi": false,
    "campaignId": null,
    "mediaId": null,
    "mediaKey": null,
    "createdAt": "2026-04-19T12:35:00.000Z",
    "previousStatus": "sent",
    "newStatus": "delivered"
  }
}
Ciclo de estados: queued → sent → delivered → read o failed.

conversation.created

Llega cuando se crea una conversación nueva (primer mensaje de un contacto).
{
  "event": "conversation.created",
  "webhookId": "...",
  "deliveredAt": "2026-04-19T12:34:56.800Z",
  "attempt": 1,
  "data": {
    "id": "uuid-conversacion",
    "contactId": "uuid-contacto",
    "phoneNumberId": "uuid-canal",
    "status": "open",
    "assignedTo": null,
    "lastMessageAt": "2026-04-19T12:34:55.000Z",
    "lastMessagePreview": "Hola, tienen stock?",
    "lastMessageDirection": "inbound",
    "lastMessageStatus": "delivered",
    "serviceWindowExpiresAt": "2026-04-20T12:34:55.000Z",
    "createdAt": "2026-04-19T12:34:55.000Z",
    "contact": {
      "id": "uuid-contacto",
      "name": "María Pérez",
      "phoneNumber": "+5491126032641"
    }
  }
}

contact.created

Llega cuando se crea un contacto nuevo (vía API o porque escribió por primera vez).
{
  "event": "contact.created",
  "webhookId": "...",
  "deliveredAt": "2026-04-19T12:34:56.800Z",
  "attempt": 1,
  "data": {
    "id": "uuid-contacto",
    "phoneNumber": "+5491126032641",
    "name": "María Pérez",
    "email": null,
    "tags": [],
    "customFields": {},
    "optedIn": true,
    "lastMessageAt": "2026-04-19T12:34:55.000Z",
    "createdAt": "2026-04-19T12:34:55.000Z"
  }
}

Idempotencia y orden

  • Un mismo evento puede entregarse más de una vez (por ejemplo si tu URL responde 200 pero la conexión se corta antes de que Waspy lo registre). Deduplicá por data.id + event.
  • Para message.received y conversation.created, contact.created se entrega primero (cuando aplica).
  • No garantizamos orden estricto entre suscripciones distintas.