Resend
Resend is the email provider for campaigns, sequence emails, manual replies and the send_email MCP
tool.
- Client
-
lib/plugins/resend-client.ts—ResendEmailClient - Topics
-
lib/services/resend-topic-service.ts - Webhooks
-
POST /api/webhooks/resend, dispatched bylib/events/resend-event-handler.ts
Configuration
RESEND_API_KEY=
RESEND_WEBHOOK_SECRET= # Svix verification; when unset, verification is skipped
Client surface
| Method | Purpose |
|---|---|
|
Verified domains, exposed at |
|
One-off transactional send |
|
Campaign send with template, topic, variables and unsubscribe headers |
|
Create or update a Resend contact for topic membership |
|
Create a Resend template from an |
|
Keep the Resend template in sync |
|
Fetch a sent message’s content |
Sending model
Resend templates are the canonical content store. An EmailVariation holds the subject and HTML in the
database and a resendTemplateId, kept in sync on create and update. templateType is always
"custom".
sendCampaign receives:
| Field | Source |
|---|---|
|
|
|
|
|
The recipient address |
|
The effective variation |
|
The variation’s Resend template, when present |
|
|
|
Resolved from contact fields with per-variable fallbacks |
|
|
UNSUBSCRIBE_LINK is always included and applied last, so no user-defined variable can overwrite it.
Resend substitutes {{{UNSUBSCRIBE_LINK}}} in both template and raw-HTML sends.
Topics
A topic segments an audience and gives Resend-managed unsubscribe alongside the application’s own.
createResendTopicForCampaign(name, campaignId) provisions one; the id is stored as
Campaign.resendTopicId. Duplicating a campaign creates a fresh topic rather than sharing the
source’s, so the copies' audiences stay independent.
upsertContact registers the recipient before sending, which is what makes topic membership and
platform-level unsubscribe work.
Unsubscribe headers (RFC 8058)
Every campaign email carries List-Unsubscribe and List-Unsubscribe-Post pointing at
/api/unsubscribe, plus an in-body link using the same URL. One-click opt-out sets
TargetEmails.newsletterOptOut, suppressing the address across every campaign in the workspace, and
publishes Contact.Unsubscribe to the CRM queue.
Webhooks
Ten event types are handled: email.sent, email.delivered, email.delivery_delayed, email.opened,
email.clicked, email.bounced, email.complained, email.suppressed, email.unsubscribed, email.received. The route verifies the Svix
signature when the secret is set, persists the raw event idempotently on the svix-id header, and
dispatches through ResendWebhookDispatcher.
See Resend email events for per-handler effects and inbound reply correlation.
Domain reputation
Two levels of sender configuration, with independent daily caps: Domain (a Resend-verified domain) and
EmailSendingDomain (a concrete From address). Each Resend subdomain is its own verified domain, so it
becomes its own Domain row rather than a child. See Email deliverability.
Per-account counters (sentCount, receivedCount, openedCount, clickedCount, bouncedCount,
unsubscribedCount) are maintained by the webhook handlers and are the practical signal for spotting an
account that is damaging the domain’s reputation.
Failure behaviour
-
No
RESEND_API_KEY— sends fail; theemailSendworkflow retries twice, then the target is left for a later tick. -
No
RESEND_WEBHOOK_SECRET— signature verification is skipped. Acceptable in development, not in production. -
A Resend outage leaves targets in
pendingwith their queue lock expiring, so they are re-leased automatically once the provider recovers.