Keep six boundaries separate
- 1. Application notification
- Persist the local notification row, recipient scope, retry generation, and stable correlation key before handoff.
- 2. Resend handoff
- Store the Resend
email_id, response class, and the RFC 5322Message-IDyou set or observe. - 3. Webhook authenticity
- Verify the raw request body and signing headers before using the payload.
- 4. Idempotency
- Claim each webhook's
svix-idonce. Resend supports retries and manual replays, so duplicate delivery is expected behavior. - 5. Ordering
- Use provider event time and terminal precedence. A late
email.sentshould not hide an earlier bounce, failure, suppression, or complaint. - 6. Owner-visible verdict
- Map every negative event into the internal alarm model. Do not leave
bouncedorcomplainedoutside the owner notification path.
Build the local incident plan. No recipient, webhook signing secret, API key, SMTP password, raw webhook body, address list, dashboard export, private log, or wallet secret is entered.
Do not paste a Resend API key, webhook signing secret, recipient address, private event body, SMTP credential, dashboard screenshot with personal data, seed phrase, private key, or wallet signature into a public issue.
Use Message-ID as the durable application key
Resend's 2026-07-08 changelog says all email webhooks and GET email endpoints now include Message-ID. The webhook event references also show data.email_id and data.message_id in email event payloads. That makes a stable RFC 5322 Message-ID a cleaner correlation key than parsing SMTP reply text or searching encrypted recipients.
- Generate one opaque Message-ID per local notification row before handoff.
- Reuse the same Message-ID on retry for the same semantic notification generation.
- Persist it with the local row, Resend
email_id, provider request time, and bounded response class. - If your mail library cannot set Message-ID, record the provider-returned Message-ID as soon as Resend exposes it and treat the fallback as a migration risk.
Do not use Message-ID as an authorization secret. It is a correlation label, not proof that a webhook is authentic.
Claim svix-id before mutating state
Resend documents retries, manual replays, and a Webhook Ingester pattern that stores each webhook under the unique svix-id. Your handler should claim that ID under a unique constraint before appending activity, changing status, or sending an owner alert.
- Verify the raw body and signing headers first.
- Insert
svix-id, event type, provider event time, received time, Message-ID, email ID, and recipient scope in one transaction. - If the insert conflicts, return success without repeating the owner-facing side effect.
- Keep replay safe for both failed and previously successful webhook messages.
Rank events by terminal meaning
Resend webhooks include positive, intermediate, and negative events. A robust handler stores every authentic event, but the owner-visible delivery verdict should move monotonically unless an operator explicitly reconciles it.
email.sent- Resend accepted the message for sending. This is not recipient delivery.
email.delivered- The receiving mail system accepted the message. This is still not inbox visibility.
email.delivery_delayed- A temporary delivery delay. Keep queue visibility and provider retry state.
email.failed- Provider-side failure before successful delivery; expose a recoverable or terminal provider action.
email.suppressed- Resend did not send because the address is suppressed. Do not retry blindly.
email.bounced- The recipient's mail server permanently rejected the email; treat it as a negative terminal outcome for that recipient.
email.complained- The recipient marked the email as spam or complained; surface it as a high-severity negative outcome.
Keep event time, received time, and precedence separate. If email.sent arrives after email.bounced, it should not clear the negative owner alarm.
Run a bounded proof before production trust
- Send one controlled message with an opaque Message-ID and a non-personal test recipient accepted by the provider's test flow.
- Verify
email.sentlinks to the local notification row by Message-ID and Resend email ID. - Use Resend's bounce, suppression, failure, or complaint test path where available; otherwise use a private non-customer canary controlled by the operator.
- Replay the same webhook and confirm the
svix-idunique claim prevents duplicate owner feed entries. - Deliver authentic events in reverse order and confirm terminal precedence holds.
- Assert every negative event used by migrations, health checks, dashboards, and owner alarms is covered by one shared verdict map.
Do not use a real customer, heir, donor, patient, student, voter, or wallet owner address to prove webhook behavior.
Safe incident packet
- Application
- Notification type, local row ID category, retry generation, UTC handoff time, and opaque Message-ID.
- Provider
- Resend email ID, event type sequence, provider event times, visible From domain, Return-Path domain, and bounded SMTP or API response.
- Webhook
- Signature verification result,
svix-idclaim result, replay behavior, and handler status code. - State
- Precedence rank, prior status, next status, whether an owner alert was emitted, and why the transition is monotonic.
- Receiver
- Only after provider acceptance: receiving domain, rejection category, quarantine or original-header evidence, and inbox visibility result.
Decode an SMTP reply locally if Resend exposes a bounded SMTP diagnostic. Analyze an original header locally only for a controlled message the operator is allowed to inspect.
Check the public sender controls after you know the actual visible From domain. DNS cannot prove webhook authenticity, duplicate handling, event ordering, or owner alert correctness.
This independent guide is not affiliated with Resend. Resend documentation, your application logs, and the receiving administrator remain the sources of truth for private events and delivery records.