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

# Webhooks

> Receive real-time event notifications for message delivery, SID status changes, and brand verification.

## Subscribe to events

```
POST /v1/webhooks
```

**Required permission:** `webhooks:manage`

```json theme={null}
{
  "url": "https://yourapp.com/webhooks/senderz",
  "events": ["message.delivered", "message.failed", "sid.status_changed"],
  "secret": "whsec_your_signing_secret"
}
```

## Event types

### Messaging events

| Event                 | Trigger                        |
| --------------------- | ------------------------------ |
| `message.queued`      | Message accepted               |
| `message.sent`        | Dispatched to carrier          |
| `message.delivered`   | Carrier delivery confirmed     |
| `message.undelivered` | Carrier non-delivery confirmed |
| `message.failed`      | Rejected pre-dispatch          |

### Sender ID events

| Event                | Trigger                                           |
| -------------------- | ------------------------------------------------- |
| `sid.status_changed` | Any SID status transition                         |
| `sid.registered`     | SID confirmed live on register                    |
| `sid.rejected`       | SID registration denied                           |
| `sid.expiring`       | SID approaching renewal deadline (30-day warning) |

### Brand events

| Event            | Trigger                   |
| ---------------- | ------------------------- |
| `brand.verified` | Brand entity verified     |
| `brand.rejected` | Brand verification failed |

## Payload format

```json theme={null}
{
  "id": "evt_x1y2z3",
  "type": "message.delivered",
  "created_at": "2026-07-17T14:30:03+10:00",
  "data": {
    "id": "msg_a1b2c3d4e5",
    "status": "delivered",
    "to": "+61400000000",
    "sender_id": "TrackFast",
    "reference": "shipment-SYD-90421",
    "delivered_at": "2026-07-17T14:30:03+10:00",
    "price": {
      "amount": "0.055",
      "currency": "AUD"
    }
  }
}
```

## Signature verification

All payloads are signed using HMAC-SHA256 with the `secret` you provide at subscription time. The signature is sent in the `X-Senderz-Signature` header.

<CodeGroup>
  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook(payload_bytes, signature, secret):
      expected = hmac.new(
          secret.encode(),
          payload_bytes,
          hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(expected, signature)
  ```

  ```javascript Node.js theme={null}
  const crypto = require("crypto");

  function verifyWebhook(payloadBuffer, signature, secret) {
    const expected = crypto
      .createHmac("sha256", secret)
      .update(payloadBuffer)
      .digest("hex");
    return crypto.timingSafeEqual(
      Buffer.from(expected),
      Buffer.from(signature)
    );
  }
  ```
</CodeGroup>

## Retry policy

Failed deliveries (non-2xx response) are retried with exponential backoff:

| Attempt | Delay      |
| ------- | ---------- |
| 1       | 30 seconds |
| 2       | 2 minutes  |
| 3       | 15 minutes |
| 4       | 1 hour     |
| 5       | 4 hours    |
| 6       | 24 hours   |

After 6 failed attempts, the webhook is marked `disabled` and an email is sent to the organisation admin.
