Email webhooks are just HTTP POSTs.
When a message is delivered, bounced, opened, or clicked, we POST signed JSON to your URL. HMAC, retries, a log per delivery — not polling, not IMAP.
Signed by default
Trust every request you receive.
HMAC-SHA256 over the raw body. Any Svix-compatible library verifies it.
Per-endpoint secret
A whsec_ key, returned once on create.
Constant-time
Timestamp checked. Replays rejected.
Replay-safe
±5 min window by default.
POST /api/webhooks HTTP/1.1
Host: acme.com
Content-Type: application/json
svix-id: msg_2a9f1c…
svix-timestamp: 1767258124
svix-signature: v1,g0Xm9c8Qk2Jp7yq3rN4bR1sT6uV8wXyZ…
{
"type": "email.delivered",
"created_at": "2026-01-01T09:00:00.000Z",
"data": {
"email_id": "email_9f2c…",
"to": ["user@example.com"],
"from": "you@acme.com",
"subject": "Your receipt from Acme"
}
}One event for every state
Subscribe to exactly what you need.
Pick events or a wildcard. Same envelope, one handler.
email.*email.sentemail.deliveredemail.delivery_delayedemail.bouncedemail.complainedemail.openedemail.clickedemail.failedemail.scheduledemail.suppressedemail.receivedSame delivery system powers inbound email: subscribe to email.received to parse and handle mail your users send you.
Developer-first
Verify a request in one call.
Raw body, secret, headers. Typed event — or it throws.
Typed events
Narrow on event.type.
Fails closed
Bad signatures never reach your handler.
import { verifyWebhook } from "unitpost";
// Pass the RAW request body — re-serializing breaks the signature.
export async function POST(req: Request) {
const payload = await req.text();
const event = verifyWebhook({
payload,
secret: process.env.UNITPOST_WEBHOOK_SECRET, // whsec_…
headers: {
"svix-id": req.headers.get("svix-id"),
"svix-timestamp": req.headers.get("svix-timestamp"),
"svix-signature": req.headers.get("svix-signature"),
},
});
if (event.type === "email.bounced") {
// …handle the bounce
}
return new Response("ok");
}Full visibility
See every delivery, trace every event.
Every attempt, with the response code your server returned.
whsec_••••••••- email.delivered1s200
- email.opened2h200
- email.bounced5h429
- email.clicked8h200
Built to survive a bad day
Retries and backoff, handled for you.
Retries on a schedule. 4xx fails fast. A broken endpoint is suspended.
Automatic retries
Up to seven times over ~19 hours. Fixed backoff.
Smart failure handling
2xx succeeds. 4xx fails fast. 429 and 5xx retry.
Auto-suspend, never hammer
20 failures in a row and we pause it. Re-enable when fixed.
Ordered & timestamped
svix-timestamp and svix-id. Dedupe and order.
Backlog & replay
Suspended events stay queued. Replay from the dashboard.
Per-delivery log
30 days of status codes and attempts.
Fully programmable
Manage endpoints over the API.
Create, test, and delete endpoints with the same scoped keys.
curl -X POST 'https://www.unitpost.com/webhooks' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'User-Agent: my-app/1.0' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/webhooks/unitpost",
"events": [
"email.delivered",
"email.bounced"
]
}'What you can build
Wire email into everything you run
React to every delivery, click, or bounce.
Sync delivery status
Update records on delivered, bounced, or complained.
Auto-suppress on bounce
Prune bounced and complained addresses.
Trigger downstream flows
Alert, ticket, or retry when a send fails.
Track engagement
Opens and clicks into your analytics or CRM.
Keep contacts in sync
Mirror contact changes into your own store.
Monitor domains
domain.updated when verification changes.
Receive inbound mail
email.received for inboxes, replies, and parsers.
Feed a data warehouse
Stream every event into your warehouse.
Included free
Webhooks on every plan, from day one
$0/ mo
- Included on the free plan — no extra charge
- 2 endpoints on free · 5 on Starter · 25 on Growth
- HMAC-signed, svix-compatible headers
- Delivery, engagement & inbound events
- 7 automatic retries over ~19 hours
- Test, replay & flush from the dashboard
Questions