Docs
Learn

Webhooks

Real-time events sent to your server.

Event types

EventWhen
email.sentAccepted for delivery
email.deliveredReached the recipient's mail server
email.delivery_delayedTemporary problem; we keep retrying
email.bouncedPermanently rejected (address is suppressed)
email.complainedMarked as spam (address is suppressed)
email.openedOpened (when images load)
email.clickedA link was clicked
email.failedCould not be sent (e.g. invalid recipient)
email.scheduled / email.canceledScheduling changes
email.receivedAn email arrived on a receiving domain

Payload

{
  "type": "email.delivered",
  "created_at": "2026-11-14T10:15:02.120Z",
  "data": {
    "email_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
    "from": "Acme <onboarding@yourdomain.com>",
    "to": ["user@example.com"],
    "subject": "Hello world",
    "tags": { "category": "welcome" }
  }
}

Verify the signature

Every request carries svix-id, svix-timestamp and svix-signature headers, signed with your endpoint's whsec_… secret. Use the open-source svix library:

import { Webhook } from 'svix';

app.post('/webhooks/email', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = new Webhook(process.env.WEBHOOK_SECRET).verify(req.body.toString(), req.headers);
    // handle event.type …
    res.sendStatus(200);
  } catch {
    res.sendStatus(400);
  }
});

Retries

If your endpoint doesn't return 2xx, we retry after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours and 10 hours. Recent deliveries and their responses are shown in Webhooks.

Was this page helpful?Send feedback