DoneTalk Developers Sign in

Webhooks

DoneTalk tells your system what happens, with a signed POST to an address of yours: a campaign started or finished, a message was delivered or read, a contact replied, a conversation was closed with its outcome.

Register an address

In Settings › Integrations › Outgoing webhooks, or through the API with the webhooks:manage scope:

curl -X POST https://api.donetalk.com/v1/c/{company}/webhooks \
  -H "Authorization: Bearer $DONETALK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-system.com/donetalk/events", "events": ["campaign.completed", "campaign.recipient.replied", "conversation.closed"]}'

The answer carries the secret only once: keep it to check the signatures.

What arrives

POST /donetalk/events 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": { "...": "the event's content" }
}

Events from a test key carry "test": true.

Check the signature

DoneTalk-Signature carries t (when it was sent, in seconds) and v1, the HMAC SHA-256 of "<t>.<exact body>" with your secret. Refuse events with a t older than 5 minutes: then no one can replay an old event.

import crypto from "node:crypto";

function validEvent(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 expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
import hmac, hashlib, time

def valid_event(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
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

The older x-donetalk-signature header (sha256= + HMAC of the body, without the time) goes along until 2027-01-21.

Answering and retries

Answer 2xx within 10 seconds; do heavy work afterwards. Without a 2xx, DoneTalk retries after 1 min, 5 min, 30 min, 2 h and 12 h. After 20 failures in a row the address shows as "Failing" (it keeps receiving). The same event may arrive more than once: use its id to process it once. Arrival order is not guaranteed: use occurredAt.

Events

EventWhen it arrives
conversation.openedA conversation started (the contact wrote or clicked an ad).
conversation.closedA conversation was closed, with the outcome, who closed it (person, AI assistant or automatic rule), the closing note, the contact, team, tags, how long it took and the campaign it came from.
conversation.assignedA conversation was assigned to a person.
conversation.transferredA conversation moved to another team or person.
conversation.reopenedA closed conversation was reopened.
contact.updatedA contact's data changed.
contact.consent_changedThe contact opted in or out of a purpose (marketing, for example).
message.receivedThe contact sent a message.
message.sentA message of ours left for WhatsApp.
message.deliveredA message reached the contact's phone.
message.readThe contact read a message.
message.failedA message could not be delivered; error.code is Meta's code.
flow.eventA flow reached a “Record event” block, with the name and data the block sets.
appointment.bookedAn appointment was booked.
appointment.rescheduledAn appointment was moved.
appointment.cancelledAn appointment was cancelled.
appointment.confirmedThe contact confirmed the appointment.
appointment.attendedThe contact attended.
appointment.no_showThe contact did not show up.
campaign.startedThe campaign started sending; its list was frozen.
campaign.pausedThe campaign paused: by a person, the API or a rule (template paused, low quality, many opt-outs, budget).
campaign.resumedThe campaign resumed sending.
campaign.completedThe campaign finished sending, with its totals.
campaign.cancelledThe campaign was cancelled.
campaign.recipient.sentThe campaign's message left for a contact.
campaign.recipient.deliveredThe campaign's message reached the contact.
campaign.recipient.readThe contact read the campaign's message.
campaign.recipient.repliedThe contact answered the campaign (the first answer), by text or tapping a button.
campaign.recipient.failedThe campaign's message failed for a contact; errorCode is Meta's code.
campaign.recipient.opted_outThe contact asked for no more campaigns (the “Stop promotions” button or a refusal at Meta).

Example of each event

conversation.opened

A conversation started (the contact wrote or clicked an ad).

{
  "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

A conversation was closed, with the outcome, who closed it (person, AI assistant or automatic rule), the closing note, the contact, team, tags, how long it took and the campaign it came from.

{
  "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

A conversation was assigned to a person.

{
  "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

A conversation moved to another team or person.

{
  "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

A closed conversation was reopened.

{
  "id": "01a3e4f5-…",
  "type": "conversation.reopened",
  "occurredAt": "2026-10-24T12:04:02.000Z",
  "customerId": "01a0c0de-…",
  "data": {
    "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677"
  }
}

contact.updated

A contact's data changed.

{
  "id": "01a3e4f5-…",
  "type": "contact.updated",
  "occurredAt": "2026-10-24T12:04:02.000Z",
  "customerId": "01a0c0de-…",
  "data": {
    "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8",
    "changes": [
      "fields",
      "displayName"
    ]
  }
}

The contact opted in or out of a purpose (marketing, for example).

{
  "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

The contact sent a message.

{
  "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

A message of ours left for 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

A message reached the contact's phone.

{
  "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

The contact read a message.

{
  "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

A message could not be delivered; error.code is Meta's code.

{
  "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

A flow reached a “Record event” block, with the name and data the block sets.

{
  "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

An appointment was booked.

{
  "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

An appointment was moved.

{
  "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

An appointment was cancelled.

{
  "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

The contact confirmed the appointment.

{
  "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

The contact attended.

{
  "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

The contact did not show up.

{
  "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

The campaign started sending; its list was frozen.

{
  "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

The campaign paused: by a person, the API or a rule (template paused, low quality, many opt-outs, budget).

{
  "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

The campaign resumed sending.

{
  "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

The campaign finished sending, with its totals.

{
  "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

The campaign was cancelled.

{
  "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

The campaign's message left for a contact.

{
  "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

The campaign's message reached the contact.

{
  "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

The contact read the campaign's message.

{
  "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

The contact answered the campaign (the first answer), by text or tapping a button.

{
  "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

The campaign's message failed for a contact; errorCode is Meta's code.

{
  "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

The contact asked for no more campaigns (the “Stop promotions” button or a refusal at 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"
  }
}

This page as Markdown