Signed webhooks and an events feed for every email

Every attempt is on record with its answer and timing, so a missed event is never a mystery.

Webhooks

https://fernbank.example/api/minket

EnabledLive

Delivery of email.bounced

AttemptAtResultTook
110:39:05502 Bad Gateway1.2 s
2+5 s502 Bad Gateway0.9 s
3+5 min200 OK0.3 s

Signing secret

whsec_<shown once>

Signed with svix headers over the exact body

Any svix library verifies a delivery with the endpoint's whsec_ secret.

import { Webhook } from "svix";

const event = new Webhook(process.env.MINKET_WEBHOOK_SECRET)
  .verify(await request.text(), {
    "svix-id": request.headers.get("svix-id"),
    "svix-timestamp": request.headers.get("svix-timestamp"),
    "svix-signature": request.headers.get("svix-signature"),
  });
In your endpoint

12 attempts in 3 days

Each retry carries the same svix-id, so your endpoint can skip a repeat.

When each attempt goes, from the first failure. The axis is compressed before 5 hours.

  1. now
  2. +5 s
  3. +5 min
  4. +30 min
  5. +2 h
  6. +5 h
  7. +10 h
  8. +10 h
  9. +10 h
  10. +10 h
  11. +10 h
  12. +10 h
  13. 3 days: stop

Replay catches up a disabled endpoint

Replay sends what it missed, oldest first, up to 100 deliveries a call.

  1. Failingevery attempt answered 503Mon
  2. Disabledafter 3 days of failuresThu
  3. Replayedwhat it missedThu

Rotate a secret without dropping a delivery

For 24 hours after a rotation, both secrets sign every delivery.

svix-signature: v1,K1lQb2w3YnE1Y0F0 v1,Hk9vUm4yT1pxR0dE
One delivery during a rotation

The same events, to pull

GET /v1/events lists them newest first, by type, email, contact and time, for 13 months.

22 event types

  • emailemail.sentemail.scheduledemail.deliveredemail.delivery_delayedemail.complainedemail.bouncedemail.openedemail.clickedemail.receivedemail.failedemail.suppressedemail.canceled
  • contactcontact.createdcontact.updatedcontact.deleted
  • domaindomain.createddomain.updateddomain.deleted
  • broadcastbroadcast.startedbroadcast.completed
  • automationautomation.completedautomation.failed

Test events and environments

Questions

What counts as delivered?

Any 2xx answer within 15 seconds.

Can an endpoint pick its events?

Yes: each endpoint subscribes to the event types it wants.