Avisos (webhooks)
DoneTalk avisa a su sistema lo que pasa, con un POST firmado a una dirección suya: una campaña empezó o terminó, un mensaje fue entregado o leído, un contacto respondió, una conversación concluyó con su desenlace.
Registrar una dirección
En Configuración › Integraciones › Webhooks de salida, o por la API con el alcance webhooks:manage:
curl -X POST https://api.donetalk.com/v1/c/{empresa}/webhooks \
-H "Authorization: Bearer $DONETALK_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://su-sistema.com/donetalk/avisos", "events": ["campaign.completed", "campaign.recipient.replied", "conversation.closed"]}'La respuesta trae el secret una sola vez: guárdelo para verificar las firmas.
Qué llega
POST /donetalk/avisos HTTP/1.1
Content-Type: application/json
User-Agent: DoneTalk-Webhooks/1.0
DoneTalk-Signature: t=1792756800,v1=5f0c…
X-DoneTalk-Event: conversation.closed
X-DoneTalk-Delivery: 01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f{
"id": "01a3e4f5-…",
"type": "conversation.closed",
"occurredAt": "2026-10-24T12:20:41.000Z",
"customerId": "01a0c0de-…",
"data": { "...": "el contenido del evento" }
}Los avisos de una clave de prueba traen "test": true.
Verificar la firma
DoneTalk-Signature trae t (la hora del envío, en segundos) y v1, el HMAC SHA-256 de "<t>.<cuerpo exacto>" con su secret. Rechace avisos con un t de hace más de 5 minutos: así nadie reenvía un aviso antiguo.
import crypto from "node:crypto";
function avisoValido(rawBody, header, secret) {
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const esperado = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
}import hmac, hashlib, time
def aviso_valido(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
esperado = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperado, parts["v1"])El encabezado antiguo x-donetalk-signature (sha256= + HMAC del cuerpo, sin hora) sigue junto hasta el 21/01/2027.
Responder y reintentos
Responda 2xx en hasta 10 segundos; haga el trabajo pesado después. Sin 2xx, DoneTalk reintenta a 1 min, 5 min, 30 min, 2 h y 12 h. Tras 20 fallas seguidas la dirección aparece como "Con fallos" (sigue recibiendo). Un mismo aviso puede llegar más de una vez: use su id para procesarlo una vez. El orden de llegada no está garantizado: use occurredAt.
Eventos
| Evento | Cuándo llega |
|---|---|
conversation.opened | Una conversación empezó (el contacto escribió o hizo clic en un anuncio). |
conversation.closed | Una conversación concluyó, con el desenlace, quién la concluyó (persona, asistente de IA o regla automática), la nota de cierre, el contacto, el equipo, las etiquetas, cuánto duró y la campaña de origen. |
conversation.assigned | Una conversación fue asignada a una persona. |
conversation.transferred | Una conversación pasó a otro equipo o persona. |
conversation.reopened | Una conversación concluida fue reabierta. |
contact.updated | Los datos de un contacto cambiaron. |
contact.consent_changed | El contacto aceptó o rechazó recibir mensajes de una finalidad (marketing, por ejemplo). |
message.received | El contacto envió un mensaje. |
message.sent | Un mensaje nuestro salió hacia WhatsApp. |
message.delivered | Un mensaje llegó al teléfono del contacto. |
message.read | El contacto leyó un mensaje. |
message.failed | Un mensaje no pudo entregarse; error.code es el código de Meta. |
flow.event | Un flujo llegó a un bloque “Registrar evento”, con el nombre y los datos que define el bloque. |
appointment.booked | Una cita fue agendada. |
appointment.rescheduled | Una cita cambió de horario. |
appointment.cancelled | Una cita fue cancelada. |
appointment.confirmed | El contacto confirmó la cita. |
appointment.attended | El contacto asistió. |
appointment.no_show | El contacto no asistió. |
campaign.started | La campaña empezó a enviar; su lista quedó cerrada. |
campaign.paused | La campaña se pausó: por una persona, la API o una regla (plantilla pausada, calidad baja, muchas bajas, presupuesto). |
campaign.resumed | La campaña volvió a enviar. |
campaign.completed | La campaña terminó de enviar, con sus totales. |
campaign.cancelled | La campaña fue cancelada. |
campaign.recipient.sent | El mensaje de la campaña salió hacia un contacto. |
campaign.recipient.delivered | El mensaje de la campaña llegó al contacto. |
campaign.recipient.read | El contacto leyó el mensaje de la campaña. |
campaign.recipient.replied | El contacto respondió a la campaña (la primera respuesta), por texto o tocando un botón. |
campaign.recipient.failed | El mensaje de la campaña falló para un contacto; errorCode es el código de Meta. |
campaign.recipient.opted_out | El contacto pidió no recibir más campañas (botón “Parar promociones” o rechazo en Meta). |
Ejemplo de cada evento
conversation.opened
Una conversación empezó (el contacto escribió o hizo clic en un anuncio).
{
"id": "01a3e4f5-…",
"type": "conversation.opened",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"handler": "flow",
"source": "inbound"
}
}conversation.closed
Una conversación concluyó, con el desenlace, quién la concluyó (persona, asistente de IA o regla automática), la nota de cierre, el contacto, el equipo, las etiquetas, cuánto duró y la campaña de origen.
{
"id": "01a3e4f5-…",
"type": "conversation.closed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701",
"assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"outcome": "converted",
"isSuccess": true,
"closedBy": {
"kind": "member",
"id": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"name": "Tayomara Batista"
},
"actorKind": "member",
"openedAt": "2026-10-24T12:00:04.000Z",
"firstResponseAt": "2026-10-24T12:05:10.000Z",
"messagesIn": 6,
"messagesOut": 7,
"outcomeLabel": {
"pt-BR": "Venda",
"en": "Sale",
"es": "Venta"
},
"outcomeCategory": "success",
"note": "Fechou o plano anual com o cupom ANA10.",
"contact": {
"name": "Ana Souza",
"phone": "5548999990001"
},
"team": {
"id": "01a0cb22-89c0-7e02-b96b-3f4731dde701",
"name": "Vendas"
},
"tags": [
{
"id": "01a12150-3610-7c00-b680-188c2b4c7313",
"name": {
"pt-BR": "VIP",
"en": "VIP",
"es": "VIP"
}
}
],
"durationSeconds": 1237,
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b"
}
}conversation.assigned
Una conversación fue asignada a una persona.
{
"id": "01a3e4f5-…",
"type": "conversation.assigned",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701",
"reason": "distribution",
"previousAssigneeId": null,
"actorKind": "system"
}
}conversation.transferred
Una conversación pasó a otro equipo o persona.
{
"id": "01a3e4f5-…",
"type": "conversation.transferred",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701",
"assigneeId": null,
"previousTeamId": null,
"previousAssigneeId": null,
"previousHandler": "flow",
"actorKind": "flow",
"reason": "Gestor de conta: Tayomara Batista"
}
}conversation.reopened
Una conversación concluida fue reabierta.
{
"id": "01a3e4f5-…",
"type": "conversation.reopened",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677"
}
}contact.updated
Los datos de un contacto cambiaron.
{
"id": "01a3e4f5-…",
"type": "contact.updated",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"changes": [
"fields",
"displayName"
]
}
}contact.consent_changed
El contacto aceptó o rechazó recibir mensajes de una finalidad (marketing, por ejemplo).
{
"id": "01a3e4f5-…",
"type": "contact.consent_changed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"channel": "whatsapp",
"purpose": "marketing",
"status": "opted_out",
"source": "keyword",
"occurredAt": "2026-10-24T12:06:00.000Z"
}
}message.received
El contacto envió un mensaje.
{
"id": "01a3e4f5-…",
"type": "message.received",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"type": "text"
}
}message.sent
Un mensaje nuestro salió hacia WhatsApp.
{
"id": "01a3e4f5-…",
"type": "message.sent",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"providerMessageId": "wamid.HBgMNTU0ODk5OTk5MDAwMRUCABEYEjE="
}
}message.delivered
Un mensaje llegó al teléfono del contacto.
{
"id": "01a3e4f5-…",
"type": "message.delivered",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "delivered",
"occurredAt": "2026-10-24T12:00:06.000Z"
}
}message.read
El contacto leyó un mensaje.
{
"id": "01a3e4f5-…",
"type": "message.read",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "read",
"occurredAt": "2026-10-24T12:03:51.000Z"
}
}message.failed
Un mensaje no pudo entregarse; error.code es el código de Meta.
{
"id": "01a3e4f5-…",
"type": "message.failed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "failed",
"occurredAt": "2026-10-24T12:00:06.000Z",
"error": {
"code": "131026",
"detail": "Message undeliverable"
}
}
}flow.event
Un flujo llegó a un bloque “Registrar evento”, con el nombre y los datos que define el bloque.
{
"id": "01a3e4f5-…",
"type": "flow.event",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"name": "lead.qualified",
"data": {
"plano": "anual",
"origem": "site"
}
}
}appointment.booked
Una cita fue agendada.
{
"id": "01a3e4f5-…",
"type": "appointment.booked",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "booked",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": null,
"cancelledAt": null,
"cancelledByKind": null,
"cancelReason": null,
"rescheduleCount": 0,
"previousStartsAt": null,
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}appointment.rescheduled
Una cita cambió de horario.
{
"id": "01a3e4f5-…",
"type": "appointment.rescheduled",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "booked",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": null,
"cancelledAt": null,
"cancelledByKind": null,
"cancelReason": null,
"rescheduleCount": 1,
"previousStartsAt": "2026-10-27T12:00:00.000Z",
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}appointment.cancelled
Una cita fue cancelada.
{
"id": "01a3e4f5-…",
"type": "appointment.cancelled",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "cancelled",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": null,
"cancelledAt": "2026-10-26T18:00:00.000Z",
"cancelledByKind": "contact",
"cancelReason": null,
"rescheduleCount": 0,
"previousStartsAt": null,
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}appointment.confirmed
El contacto confirmó la cita.
{
"id": "01a3e4f5-…",
"type": "appointment.confirmed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "confirmed",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": "2026-10-26T14:00:00.000Z",
"cancelledAt": null,
"cancelledByKind": null,
"cancelReason": null,
"rescheduleCount": 0,
"previousStartsAt": null,
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}appointment.attended
El contacto asistió.
{
"id": "01a3e4f5-…",
"type": "appointment.attended",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "attended",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": null,
"cancelledAt": null,
"cancelledByKind": null,
"cancelReason": null,
"rescheduleCount": 0,
"previousStartsAt": null,
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}appointment.no_show
El contacto no asistió.
{
"id": "01a3e4f5-…",
"type": "appointment.no_show",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"id": "01a2f00d-1234-7abc-8def-0123456789ab",
"agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0",
"agendaName": "Visitas aos imóveis",
"typeId": "01a1228c-c58f-796a-b3aa-54a953711c71",
"typeName": "Visita ao imóvel",
"typeColor": "#1daa61",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"contactName": "Ana Souza",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"channelId": "01a0cccc-0000-7000-8000-000000000002",
"memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a",
"memberName": "Tayomara Batista",
"holderIds": [
"01a0cac1-4a6f-7646-b5f8-c1d19090016a"
],
"status": "no_show",
"startsAt": "2026-10-27T13:00:00.000Z",
"endsAt": "2026-10-27T14:00:00.000Z",
"timezone": "America/Sao_Paulo",
"location": "Rua Bahia, 120 – Higienópolis, São Paulo",
"locationKind": "address",
"onlineUrl": null,
"answers": {
"imovel": "AP-2231"
},
"notes": null,
"source": "api",
"createdByKind": "api_key",
"createdById": null,
"confirmedAt": null,
"cancelledAt": null,
"cancelledByKind": null,
"cancelReason": null,
"rescheduleCount": 0,
"previousStartsAt": null,
"publicToken": "r3WqZ8",
"createdAt": "2026-10-23T13:02:11.000Z"
}
}campaign.started
La campaña empezó a enviar; su lista quedó cerrada.
{
"id": "01a3e4f5-…",
"type": "campaign.started",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "running",
"audience": 1240,
"skipped": 24,
"startedAt": "2026-10-24T12:00:00.000Z"
}
}campaign.paused
La campaña se pausó: por una persona, la API o una regla (plantilla pausada, calidad baja, muchas bajas, presupuesto).
{
"id": "01a3e4f5-…",
"type": "campaign.paused",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "paused",
"reason": "optout_rate",
"by": "system"
}
}campaign.resumed
La campaña volvió a enviar.
{
"id": "01a3e4f5-…",
"type": "campaign.resumed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "running",
"by": "api_key"
}
}campaign.completed
La campaña terminó de enviar, con sus totales.
{
"id": "01a3e4f5-…",
"type": "campaign.completed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "completed",
"totals": {
"audience": 1216,
"sent": 1216,
"delivered": 1198,
"read": 874,
"replied": 141,
"failed": 18,
"skipped": 24,
"optedOut": 6
}
}
}campaign.cancelled
La campaña fue cancelada.
{
"id": "01a3e4f5-…",
"type": "campaign.cancelled",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"status": "cancelled",
"by": "member"
}
}campaign.recipient.sent
El mensaje de la campaña salió hacia un contacto.
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.sent",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"phone": "5548999990001",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"at": "2026-10-24T12:00:04.000Z"
}
}campaign.recipient.delivered
El mensaje de la campaña llegó al contacto.
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.delivered",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"phone": "5548999990001",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"at": "2026-10-24T12:00:06.000Z"
}
}campaign.recipient.read
El contacto leyó el mensaje de la campaña.
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.read",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"phone": "5548999990001",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"at": "2026-10-24T12:03:51.000Z"
}
}campaign.recipient.replied
El contacto respondió a la campaña (la primera respuesta), por texto o tocando un botón.
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.replied",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"buttonIndex": 0,
"text": "Quero o cupom"
}
}campaign.recipient.failed
El mensaje de la campaña falló para un contacto; errorCode es el código de Meta.
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.failed",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"phone": "5548999990001",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889",
"errorCode": "131026"
}
}campaign.recipient.opted_out
El contacto pidió no recibir más campañas (botón “Parar promociones” o rechazo en Meta).
{
"id": "01a3e4f5-…",
"type": "campaign.recipient.opted_out",
"occurredAt": "2026-10-24T12:04:02.000Z",
"customerId": "01a0c0de-…",
"data": {
"campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
"conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677",
"via": "button"
}
}