---
title: "Event webhooks: hear what happens in Dazza — Dazza help"
description: "Get a signed POST to your own endpoint when a conversation starts, is handed over or resolved, or a message or contact arrives. Retries and a delivery log."
url: https://dazza.io/help/event-webhooks
updated: 2026-10-27
---

# 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 read · Updated 27 Oct 2026 · 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](https://dazza.io/help/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](https://dazza.io/help/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](https://dazza.io/help/webhooks):

```
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.
