Event webhooks

Dazza tells your systems the moment a conversation starts, is handed over or resolved, a message arrives or a new customer appears.

3 MIN READUPDATED 7 SECTIONS

Event webhooks send a signed JSON request to your endpoint when something happens in Dazza. Use them to log every conversation in your CRM, open a ticket when a customer is handed over, or close the loop when a conversation is resolved.

To ask Dazza for data or make changes, use the REST API.

Add an endpoint

Admins add endpoints in Settings → Developers → Event webhooks:

  1. Enter your endpoint’s address. It must be public and start with https. Dazza doesn’t follow redirects.
  2. Choose the events it should get.
  3. Copy the signing secret. It’s shown once.

Send test posts a sample of one of its events, marked "test": true, and shows what your endpoint replied. You can change the events, pause an endpoint, or make a new secret at any time. A workspace can have up to 10 endpoints.

Events

Event When
conversation.created A customer starts a conversation on any channel.
conversation.handed_over Dazza hands a conversation to the team, or the customer asks for a person.
conversation.resolved Someone resolves a conversation, in the inbox or through the API.
message.created A customer, Dazza or the team writes a message. Email drafts count once a person sends them.
contact.created Dazza meets a new customer it knows by email, phone or name.
rating.created A customer rates a conversation Good, Okay or Poor at the end of a chat.
rating.updated A customer adds a comment to their rating, or changes it, in the minutes after rating.

Conversations in the Agent preview never send events.

What Dazza sends

POST https://your-system.example/dazza-events
content-type: application/json
x-dazza-event: conversation.handed_over
x-dazza-delivery: dlv_8k2m…
x-dazza-timestamp: 1792860533
x-dazza-signature: sha256=9f2c…
{
  "id": "ev_3h7q…",
  "type": "conversation.handed_over",
  "created_at": "2026-10-27T10:42:00.000Z",
  "workspace_id": "wks_…",
  "data": {
    "conversation": {
      "object": "conversation",
      "id": "cnv_9x2k…",
      "channel": "web",
      "status": "open",
      "with": "team",
      "subject": "Can I change my booking?",
      "contact": { "object": "contact", "id": "cnt_4hq1…", "name": "Sam Taylor", "email": "sam@example.com", "attributes": {} },
      "handover": { "at": "2026-10-27T10:42:00.000Z", "reason": "customer_request", "reason_label": "Asked for a person", "summary": "Sam wants to move their booking to Friday." },
      "…": "…"
    }
  }
}

data holds the same objects the REST API returns:

  • conversation.* events: conversation. conversation.resolved adds resolved_by (team or ai).
  • message.created: message, plus a short conversation with its id, channel, status and with.
  • contact.created: contact.
  • rating.created and rating.updated: rating with conversation_id, value (good, okay or poor), comment and rated_at, plus the conversation. Most comments arrive as rating.updated, a few seconds after the rating.

Check the signature

Each endpoint has its own secret. Dazza signs the timestamp and the raw body with it, the same way as Call your own system:

import crypto from "node:crypto";

const expected = "sha256=" + crypto
  .createHmac("sha256", process.env.DAZZA_WEBHOOK_SECRET)
  .update(`${req.headers["x-dazza-timestamp"]}.${rawBody}`)
  .digest("hex");

const given = req.headers["x-dazza-signature"] ?? "";
if (given.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given))) {
  return res.status(401).end();
}

Check against the raw body, before parsing it, and reject old timestamps so a request can’t be replayed later.

Reply quickly, then do the work

Answer with any 2xx within 10 seconds. Anything else, or no answer, counts as a failure.

Retries

A failed delivery is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours and 24 hours: eight tries over about two days. Then Dazza stops and marks it failed.

Because of retries, the same event can arrive more than once, and events can arrive out of order. Use the event id to ignore repeats, and created_at to put them in order. x-dazza-delivery is the same on every try of one delivery.

The delivery log

Each endpoint shows how many deliveries landed, are retrying or failed in the last 30 days. Deliveries lists the latest, with each try’s status code and timing, and when the next try is due. Records are kept for 30 days.

Still stuck? A person reads every message. Contact us ↗