how-to · sourced answer

How Do Resend Webhooks Work?

Resend webhooks work by sending an HTTPS POST with a JSON event payload to your registered endpoint when an email, contact, domain, or suppression event occurs. Your endpoint should verify the signature against the raw request body, process the event idempotently, and return a successful response promptly.

The Resend webhook workflow

The workflow begins when you create a public HTTPS endpoint and register it in Resend with the event types your application needs. When a matching event occurs, Resend sends a POST request containing a JSON payload. The payload includes a type such as email.sent, email.delivered, email.bounced, or email.complained, a creation time, and event-specific data. Route processing by the type field instead of assuming every payload has the same shape.

Verify the request before processing it

Read the request as raw text and verify it with the webhook signing secret plus the svix-id, svix-timestamp, and svix-signature headers. Do this before parsing or acting on the payload. Parsing JSON and then serializing it again can change the bytes and make a legitimate signature fail. Reject requests that do not pass verification, and keep the signing secret in a secret manager or protected environment variable rather than in source code.

Make event handling idempotent

Resend documents at-least-once delivery, so the same event may reach your endpoint more than once. Store the svix-id with a uniqueness constraint and skip business logic when that identifier has already been processed. Do not rely on arrival order either, because retries and network delays can reorder events. Use the event created_at value when sequencing matters, and model status changes so an older event cannot overwrite newer state accidentally.

Acknowledge quickly and process safely

Return HTTP 200 after the event has been verified and durably recorded, then perform slower work through a queue or background worker. A timeout or non-success response causes another delivery attempt, so long synchronous handlers create avoidable duplicates. Separate ingestion from side effects such as updating a suppression record, notifying support, or recording a bounce. Each side effect should also be safe to repeat or guarded by the stored event identifier.

Test retries, replays, and failure recovery

Test the endpoint with representative event types before production, including invalid signatures, duplicate identifiers, out-of-order timestamps, and temporary database failures. Resend retries failed deliveries on a backoff schedule and lets you replay both failed and successful webhook messages. Use replay to recover after an outage or validate updated handler code, but keep deduplication active so recovery does not repeat customer-facing side effects.

Questions teams ask

Which response should a Resend webhook endpoint return?

Return HTTP 200 after the request is verified and the event is durably accepted. Slow work should continue asynchronously so the provider does not retry because of a timeout.

Why must the raw request body be preserved?

The signature covers the original request bytes. Parsing and re-serializing JSON can alter those bytes, causing verification to fail even when the request is legitimate.

Can a Resend webhook event be delivered more than once?

Yes. Resend documents at-least-once delivery, so handlers must deduplicate events, typically by storing the unique svix-id before applying business side effects.

Are Resend webhook events delivered in order?

No. Network delays and retries can change arrival order. Use event timestamps and state-transition rules when your application must reconstruct a reliable sequence.

How should failed Resend webhook deliveries be recovered?

Resend automatically retries failed deliveries and also supports manual replay. Fix the endpoint first, then replay needed events while keeping idempotency checks enabled.

Primary sources