Email delivery event webhooks

Your email provider POSTing to your app the moment a message is delivered, bounced, opened, or reported as spam, instead of you polling.

webhook eventscallbacks when my mail bouncesemail event callbacksbounce webhookdelivery notifications from my email apisendgrid event webhookses sns notificationshow do I know if the email actually arrived

See it

Live demo coming soon

What it is

Your send API returns a 202 and a message ID, which only means the provider accepted the message into its queue. Everything that actually matters happens minutes to days later: delivered, deferred, bounced, complained (someone hit 'report spam'), opened, clicked, unsubscribed. Delivery event webhooks are the provider POSTing those events to an endpoint you own as they happen, instead of you polling an API that was never designed for it.

Wire them to do work, not just to write logs. Hard bounces and complaints should write straight to your suppression list without a human in the loop, because both are permanent and both cost you reputation every time you repeat them. Soft bounces feed a retry policy. Engagement events feed a sunset policy. Every ESP has a version: SendGrid Event Webhook, Postmark webhooks, Resend webhooks, SES via SNS or EventBridge.

The gotchas are the usual webhook ones plus one email-specific twist. Delivery is at-least-once and out of order, so an 'opened' can arrive before its 'delivered': key on the provider's unique event ID where one exists, and make handlers idempotent. Deduping on message ID plus event type is the tempting shortcut that quietly eats real events, since one message can legitimately produce several deferrals or several clicks. Verify the signature, since the endpoint is public and anyone can POST fake bounces to poison your suppression list. Return 2xx fast and process async, or retries pile up and the provider disables the endpoint. And treat open events as mush: Apple Mail Privacy Protection prefetches images, so plenty of 'opens' are nobody.

Ask AI for it

Build me an email event webhook endpoint (POST /webhooks/email) for <provider>. Requirements: verify the provider's signature on the raw request body before parsing, return 200 immediately and hand the payload to a background queue, and dedupe on the provider's own unique event ID. If this provider does not supply one, build a provider-specific composite key from message ID, event type, attempt or recipient, status code, and event timestamp, so a literal replay is idempotent while separate attempts and repeated deferrals are still stored as distinct events. In the worker, handle delivered, bounce (split hard vs soft), complaint, unsubscribe, open, and click: hard bounces and complaints insert into a permanent suppression table checked before every send, soft bounces increment a counter that suppresses after N consecutive failures, engagement events update a last_engaged_at column. Include retry-safe error handling and a table schema.

You might have meant

hard bouncesoft bouncesuppression listcomplaint feedback loopbounce processing