/email-for-startups 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-05-07 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.

related startup email pages