~/email-for-developers providers ↗
guide

Email Webhooks

Email webhooks turn provider-side delivery events into application state. A good endpoint verifies the signature, acknowledges quickly, stores an immutable event record, and processes the business effect from a queue. The goal is not to do everything in the request handler. The goal is to never lose or double-apply an event.

last updated 2026-08-13 4 sections
section 01

Webhook payload structure

Most providers send a message identifier, event type, recipient, timestamp, and provider-specific metadata. Some send one event per request. Others batch several events into one payload. Normalize the incoming shape before downstream systems depend on it.

fieldwhy it mattersstorage rule
provider_event_idDedupes retries and replayed callbacks.Unique index when available.
message_idConnects delivery state to the original send.Store with the outbound send row.
event_typeRoutes bounce, complaint, delivery, open, and click events.Normalize to internal enum.
raw_payloadKeeps audit data for provider disputes.Store before processing.
section 02

Signature verification

Verify the signature before parsing business meaning from the payload. Different providers sign different material: raw body, timestamp plus body, or provider-specific fields. The endpoint should reject stale timestamps and never rebuild the signed body from parsed JSON.

  • ok Read the raw request body before JSON parsing.
  • ok Verify timestamp tolerance when the provider includes one.
  • ok Compare signatures with a constant-time function.
  • ok Keep test-mode secrets separate from production secrets.
  • ok Log rejected signatures without storing sensitive payload fields.
section 03

Acknowledgment and retry behavior

Return a 2xx response after the event is authenticated and stored. Heavy work belongs in a queue. Providers retry failed callbacks, which means the endpoint must tolerate duplicate delivery and out-of-order arrival.

eventcommon actionidempotency need
deliveredMark message as accepted by the mailbox provider.Do not move a bounced message back to delivered.
hard_bounceSuppress the address for future sends.Apply once per recipient and stream.
complaintSuppress and flag reputation risk.Treat as terminal.
open or clickRecord engagement signal if tracking is enabled.Dedup high-volume repeats.
section 04

Processing and storage pattern

The safest pattern is receive, verify, store, enqueue, acknowledge. A worker can then apply state transitions, update suppression lists, notify support, or sync analytics without keeping the provider waiting.

  • ok Persist raw payload and normalized fields in the same transaction.
  • ok Use a unique event key to make replay harmless.
  • ok Process terminal states such as hard bounce and complaint before engagement states.
  • ok Alert when webhook volume drops to zero for an active stream.

reading this as developers picking email infrastructure

The question here is which one a backend engineer would rather operate. That means SDK depth in the language already in use, whether a retry can safely be replayed, how much the event log tells you when a customer says the email never arrived, and whether the pricing curve stays sane as volume grows.

Applied to email webhooks, that means weighing developer experience, SDK breadth, idempotency keys, and operating track record ahead of the rest, against password resets, receipts, and magic links shipped from application code.

related pages