# Webhooks

> Get signed HTTP notifications when emails are delivered, bounce, are opened or clicked, arrive on your inbound domain, or when resources change.

Webhooks push events from Emailit to your application as they happen, so you don't have to poll the API. Use them to update delivery status in your database, stop emailing addresses that bounce or complain, react to opens and clicks, process [inbound email](/docs/inbound/), or sync contacts and suppressions.

## How it works

1. **You register an endpoint.** Create a webhook with a name and an HTTPS URL in the dashboard or with the API. Emailit generates a signing secret for it.
2. **Something happens.** Emailit records an [event](/docs/logs/events/), for example `email.delivered`, and queues it for every enabled webhook that subscribes to that event type and whose payload filter matches.
3. **Emailit sends a batch.** Within seconds, Emailit sends a `POST` request whose body is a JSON array of up to 100 queued events, oldest first. Requests to one webhook are sent one at a time.
4. **Your endpoint answers.** Any `2xx` status within 30 seconds marks every event in the batch as delivered. Anything else, including a timeout or a redirect, is a failure, and the batch is [retried](/docs/webhooks/retries-and-failures/) for about three days.

Each request has these headers:

| Header | Value |
| --- | --- |
| `Content-Type` | `application/json` |
| `User-Agent` | `Emailit-Webhooks/2.0` |
| `X-Emailit-Signature` | Hex HMAC-SHA256 of `{timestamp}.{raw body}`, keyed with the webhook secret. |
| `X-Emailit-Timestamp` | Unix time in seconds when the request was signed. |

See [Webhook requests](/docs/webhooks/webhook-requests/) for the full format and [Request signature](/docs/webhooks/request-signature/) for verification code.

## Quick example

This Express handler verifies the signature, then handles each event in the batch:

```javascript title="webhook.js"

const app = express();

app.post('/webhooks/emailit', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.get('X-Emailit-Timestamp') ?? '';
  const signature = req.get('X-Emailit-Signature') ?? '';
  const expected = crypto
    .createHmac('sha256', process.env.EMAILIT_WEBHOOK_SECRET) // whsec_...
    .update(`${timestamp}.`)
    .update(req.body)
    .digest('hex');

  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
  const a = Buffer.from(signature);
  const b = Buffer.from(expected);
  const valid = a.length === b.length && crypto.timingSafeEqual(a, b);
  if (!fresh || !valid) return res.status(401).send('Invalid signature');

  for (const event of JSON.parse(req.body)) {
    switch (event.type) {
      case 'email.delivered':
        console.log(`Delivered ${event.data.object.id} to ${event.data.object.to}`);
        break;
      case 'email.bounced':
      case 'email.complained':
        console.log(`Stop sending to ${event.data.object.to}`);
        break;
    }
  }

  res.sendStatus(200);
});

app.listen(3000);
```

## What you can subscribe to

Webhooks cover email delivery and engagement (`email.delivered`, `email.bounced`, `email.clicked` and more), inbound mail (`email.received`), and changes to domains, audiences, subscribers, contacts, templates, suppressions, email verifications and campaigns. A new webhook created in the dashboard receives every event; you can narrow it to specific types later. See [Event types](/docs/webhooks/event-types/).

On Pro, Business and Custom plans, a payload filter can limit a webhook to events that match rules, for example only emails to one domain.

## Limits

| | Pay as you go | Pro | Business | Custom |
| --- | --- | --- | --- | --- |
| Webhook endpoints | 3 | 10 | 100 | 100 |
| Webhook payload filters | — | Up to 25 rules | Up to 25 rules | Up to 25 rules |

The webhook page shows how many endpoints you're using, for example **2/3 used**. When you reach the limit, **Add webhook** is disabled until you delete one or [upgrade](/pricing/). Each webhook can send at most 5 test events per minute.

## Get started

  - [Set up a webhook](/docs/webhooks/set-up/): Create an endpoint, choose events, add filters and send a test.
  - [Verify signatures](/docs/webhooks/request-signature/): Check that requests come from Emailit, in six languages.
  - [Event types](/docs/webhooks/event-types/): Every event Emailit sends and when.
  - [Retries and failures](/docs/webhooks/retries-and-failures/): What happens when your endpoint is down.

---
Source: https://emailit.com/docs/webhooks/
