> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendbaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Delivery is asynchronous. Webhooks tell your application what happened to each message without polling.

When a message is sent, delivered, bounces, gets a complaint, fails, or a recipient unsubscribes or opts out, Sendbaze POSTs a signed JSON event to your endpoint. Set one up in minutes:

**1. Add an endpoint**

Open **Webhooks** in the dashboard, enter an HTTPS URL and choose the [event types](https://docs.sendbaze.com/learn/webhooks/events.md) you want, or leave the filter empty for every event. Or call `POST /v1/webhooks` with scope `webhooks:write`.

```bash theme={"dark"}
curl https://api.sendbaze.com/v1/webhooks \
  -H "Authorization: Bearer $SENDBAZE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://api.yourshop.co.za/webhooks/sendbaze", "events": ["email.bounced", "email.complained"] }'
```

**2. Store the secret**

Each endpoint gets a signing secret (`whsec_…`), shown once. Put it in an environment variable on the server that receives the events.

**3. Verify and handle events**

Check the `Sendbaze-Signature` header against the raw body before parsing, then act on `type`. See [verify the signature](https://docs.sendbaze.com/learn/webhooks/verify-signature.md).

**4. Send a test event**

Press **Send test event** or call `POST /v1/webhooks/{id}/test`. A `webhook.test` event is delivered regardless of the filter, and the delivery log shows the attempt, your response status and the time it took.

## Payload

```http theme={"dark"}
POST /webhooks/sendbaze HTTP/1.1
Content-Type: application/json
Sendbaze-Signature: t=1758528842,v1=6f1c0a9e2d...
Sendbaze-Event-Id: evt_01j9x7m3p5q7r9s1t3u5v7w9x1

{
  "id": "evt_01j9x7m3p5q7r9s1t3u5v7w9x1",
  "type": "email.bounced",
  "occurredAt": "2026-09-22T08:14:04.201Z",
  "data": {
    "id": "em_01j9x7k2r4m8q3v5n6b7c8d9e0",
    "channel": "email",
    "class": "transactional",
    "status": "bounced",
    "to": "thandi@example.com",
    "from": "orders@yourshop.co.za",
    "subject": "Your order #1042 has shipped",
    "tags": ["order-shipped"],
    "error": { "code": "hard_bounce", "message": "550 5.1.1 The email account does not exist." },
    "createdAt": "2026-09-22T08:14:02.114Z",
    "sentAt": "2026-09-22T08:14:02.688Z",
    "deliveredAt": null
  }
}
```

`data` is the message object that `GET /v1/emails/{id}` or `GET /v1/sms/{id}` returns, without the `events` array.

## Requirements for your endpoint

* HTTPS on a public host. Private and local network addresses are refused, and redirects are not followed.
* Answer with any `2xx` within 10 seconds. Do the real work after responding, for example by putting the event on a queue.
* Expect duplicates and out-of-order delivery. De-duplicate with `Sendbaze-Event-Id`, order with `occurredAt`.

## Managing endpoints

Everything on the dashboard page is also in the API:

| Endpoint | Purpose |
| - | - |
| `POST /v1/webhooks` | Create; the response carries `secret` once |
| `GET /v1/webhooks`, `GET /v1/webhooks/{id}` | List and read |
| `PATCH /v1/webhooks/{id}` | Change `url`, `description`, `events` or `enabled` |
| `DELETE /v1/webhooks/{id}` | Remove the endpoint and its delivery log |
| `POST /v1/webhooks/{id}/test` | Queue a `webhook.test` event |
| `GET /v1/webhooks/{id}/deliveries` | The delivery log, filter by `status` |
| `POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay` | Send an event again with a fresh signature |

The Node.js SDK covers all of this as `sendbaze.webhooks.*` and exports `verifyWebhookSignature`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.