---
title: "How email webhooks work (they're POST)"
description: "An email webhook is an HTTP POST to your URL when a message is delivered, bounced, opened, or clicked — not polling, not IMAP."
url: https://www.unitpost.com/blog/concepts/how-email-webhooks-work
section: Blog
updated: 2026-08-28
---
# 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.

## How email webhooks work (they're POST)

> An email webhook is an HTTP POST to your URL when a message is delivered, bounced, opened, or clicked — not polling, not IMAP.

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 (/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.

## FAQ

### 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.

## Related

- [Move off SendGrid SMTP after the free plan ended](https://www.unitpost.com/blog/concepts/move-off-sendgrid-smtp): SendGrid retired its free plan. Point the same SMTP client at Unitpost — host, username unitpost, API key as password — without rewriting your app.
- [How to let an AI agent send email safely](https://www.unitpost.com/blog/agents/send-email-from-ai-agent): The concrete controls that make agent-initiated email safe: scoped credentials, a verified-domain gate, idempotency, approval before send, and an audit trail.
- [How to fix an SPF record that isn't found](https://www.unitpost.com/blog/troubleshooting/spf-record-not-found): Why an SPF lookup returns nothing even after you've added the record, and how to diagnose it: propagation, wrong host, quoting, and the one-SPF-record rule.
