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

# Webhooks

> Receive WADial token, pairing, connection, and receipt events in your application.

Create webhook endpoints from the dashboard or API.

```http theme={null}
POST /api/v1/webhooks
Authorization: Bearer <api_key>
Content-Type: application/json
```

```json theme={null}
{
  "url": "https://example.com/wadial/webhook",
  "events": ["message.received", "message.receipt", "connection.state"]
}
```

WADial sends events as signed `POST` requests.

```http theme={null}
POST /your/webhook/url
Content-Type: application/json
wadial-event-id: 019f...
wadial-event-type: message.receipt
wadial-signature: t=1782751000,v1=<hex_hmac_sha256>
```

```json theme={null}
{
  "id": "019f...",
  "type": "message.receipt",
  "createdAt": "2026-06-29T16:00:00.000Z",
  "sessionId": "019eff5e-e24e-74ce-a9bb-ccd97e6946b6",
  "data": {}
}
```

## Verify signatures

The signature is an HMAC SHA-256 over:

```text theme={null}
<timestamp>.<raw_json_body>
```

Use the signing secret shown once when you create the webhook.

```js theme={null}
import { createHmac, timingSafeEqual } from "node:crypto";

function verifyWadialSignature({ rawBody, header, secret }) {
  const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}
```

## Events

* `session.created`
* `session.deleted`
* `connection.state`
* `auth.qr`
* `auth.paired`
* `message.received`
* `message.sent`
* `message.receipt`
* `message.failed`
* `stanza.error`
* `stream.failure`

Return a `2xx` response after processing the event. Non-`2xx` responses count as failed deliveries in the dashboard.
