How email webhooks work (they're POST)
An email webhook is an HTTP POST. Your provider sends a signed JSON body to a URL you register the moment something happens to a message — delivered, bounced, opened, clicked, complained. You verify the signature, return 2xx quickly, and do slow work afterwards. That is the whole mechanism; IMAP and polling are a different job.
Unitpost ·
Email webhooks are not a mailbox protocol. They are the same pattern as Stripe or GitHub: something happened, here is a POST.
What gets POSTed
A JSON envelope with the event name, the message id, and enough fields to update your own records. You do not fetch the message body from IMAP. You already sent it; this is the outcome.
The product surface that does this for Unitpost is /webhooks — HMAC, retries, a 30-day log.
Verify, then 2xx
Check the signature against the raw body. Parsing JSON and re-serializing it changes bytes and the HMAC will not match. Return 2xx as soon as the event is durably recorded. Slow work after the response, or a timeout counts as failure and you get the same POST again.
Inbound mail into your app is the same pipeline (`email.received`) — still a POST, still not IMAP.
Frequently asked questions
Are email webhooks GET or POST?
POST. The provider pushes an event to you. A GET would be you polling them, which is not a webhook.
What if my endpoint is down?
Honest providers retry with backoff, then stop hammering you. Unitpost retries 7 times over about 19 hours and suspends the endpoint after 20 consecutive failures. You can replay from the delivery log.
How do I avoid handling the same event twice?
Dedupe on the delivery id in the signature headers (svix-id on Unitpost). Treat the handler as idempotent. Timeouts look like failures and get retried.