# Managing webhooks

> Subscribe an HTTPS endpoint to delivery and engagement events. MailBlastr POSTs a signed JSON payload to your URL and retries with backoff on failure.

Webhooks push email events to your own server in near-real time, so you do not have to poll. When an email is delivered, opened, clicked, bounces, or is complained about, MailBlastr sends an HTTP `POST` with a JSON body to the endpoint(s) you have configured.

Each delivery is signed so you can verify it really came from MailBlastr — see [Verify webhook requests](https://www.mailblastr.com/docs/webhooks/verify).

## Configuring an endpoint

1. **Add an endpoint** — In the dashboard, add a webhook with the HTTPS URL that should receive events. The URL must be publicly reachable over HTTPS and resolve to a public IP (private/loopback addresses are rejected).
2. **Choose events** — Select which events the endpoint should receive. Events you do not subscribe to are never delivered. See [Event types](https://www.mailblastr.com/docs/webhooks/events) for the full list.
3. **Save the signing secret** — A `whsec_` signing secret is generated for the endpoint and shown once. Store it securely — you will use it to verify every incoming request.
4. **Verify and go live** — Use the dashboard Test button to send a sample delivery, confirm your endpoint returns a 2xx, then start handling live events.

> **Warning:** Your endpoint must respond with a 2xx status. Any non-2xx response (or a timeout) counts as a failed delivery and is retried.

Webhooks can also be managed programmatically via the API — see [Create webhook](https://www.mailblastr.com/docs/api/webhooks-create), [List webhooks](https://www.mailblastr.com/docs/api/webhooks-list), and the retrieve/update/delete endpoints. The create and retrieve calls return the `whsec_` signing secret in the response body.

## The payload

Each delivery is a JSON body in the envelope `{ "type", "created_at", "data" }`, where `data` holds the resource-specific fields for that event. See [Event types](https://www.mailblastr.com/docs/webhooks/events) for the envelope and a sample, and the per-event pages for each `data` shape.

## The signing secret

Each endpoint has its own signing secret. MailBlastr uses it to compute an HMAC-SHA256 signature over the raw request body and sends that in the `X-Mailblastr-Signature` header. Keep the secret server-side — anyone with it can forge events. The secret is stored encrypted at rest.

## Delivery, timeouts, and retries

Each delivery is a single `POST` with a 10-second timeout. A delivery is considered successful only on a 2xx response.

- On failure, MailBlastr retries — up to **5 attempts total** (the initial attempt plus 4 retries).
- Retries use an increasing backoff of roughly **1, 5, 30, then 120 minutes**.
- The attempt number is included in each request as the `X-Mailblastr-Attempt` header (starting at 1), so you can detect retries.
- An endpoint that fails **50 consecutive deliveries** is automatically disabled. Re-enable it from the dashboard once your endpoint is healthy.

> **Note:** Make your handler idempotent. Because failed deliveries retry and event transports can redeliver, your endpoint may occasionally receive the same event more than once.

## Delivery guarantees

- **At-least-once** — every event is delivered at least once, but in rare cases (e.g. a network timeout after your server already processed the event) it may arrive more than once. Deduplicate on the `svix-id` header, which is unique per event and stable across retries.
- **No ordering guarantee** — events are sent as they occur, but network conditions and retries mean they can arrive out of order. For example, `email.opened` may arrive before `email.delivered` for the same email. If order matters, sort by the `created_at` timestamp in the payload after receipt.
