Skip to Content
EmailMigrate from Resend

Migrate from Resend

Resend and Retransmit send email the same way: one call with from, to, subject, and a body, returning { data, error } instead of throwing. Most of a migration is swapping the client. The one real change is templates: Retransmit takes html and text strings, so React Email components are rendered in your code before the send.

This guide covers email. SMS and WhatsApp use the same client and are documented under their own sections.

Install the SDK

npm i retransmit.dev

Create an API key on the dashboard  and put it in RETRANSMIT_API_KEY. Your Resend key keeps working until you remove it, so you can run both side by side while you switch traffic.

Verify your domain

Domain verification does not carry over. Add your sending domain in the dashboard and publish the SPF and DKIM records it gives you. Sends from an unverified domain are rejected with domain_not_verified. See Domains.

Swap the client

The constructor and the send call have the same shape.

import { Resend } from "resend"; const resend = new Resend(process.env.RESEND_API_KEY); const { data, error } = await resend.emails.send({ from: "Acme <hello@yourdomain.com>", to: "user@example.com", replyTo: "support@yourdomain.com", subject: "Your receipt", html: "<p>Thanks for your order!</p>", text: "Thanks for your order!", tags: [{ name: "category", value: "receipt" }], });

data.id identifies the email in Get Email and in webhook events. The response also carries status (queued) and created_at. Errors have a code and a message. The codes are listed under Errors.

Batch sends move the same way: resend.batch.send([...]) becomes retransmit.batch.send([...]). See Send Batch.

Render React Email to HTML

Resend accepts a react prop and renders it for you. Retransmit does not render templates, so call React Email’s render yourself and pass the result as html. Your templates do not change.

import { Resend } from "resend"; import { WelcomeEmail } from "./emails/welcome"; const resend = new Resend(process.env.RESEND_API_KEY); await resend.emails.send({ from: "Acme <hello@yourdomain.com>", to: "user@example.com", subject: "Welcome to Acme", react: <WelcomeEmail name="Jane" />, });

A few notes on render:

  • render is exported by @react-email/components, which you already have if you use React Email. If you want a smaller dependency, install @react-email/render and import it from there.
  • Since React Email 1.0, render returns a promise. On older versions it returns the string directly, so drop the await.
  • { plainText: true } produces the text body from the same component. It is optional, but sending both html and text helps deliverability.
  • Rendering happens in your process, so a template error surfaces before the request goes out. Nothing is queued.

For a batch, render each email before building the array.

Move your webhooks

Create an endpoint on the dashboard’s Webhooks page and point it at your handler. Retransmit uses the same event names as Resend for email (email.sent, email.delivered, email.bounced, email.opened, and so on), but the payload and the signature differ:

  • Deliveries are signed with retransmit-timestamp and retransmit-signature headers, not Svix headers. Replace the Svix verification with the check in Verifying signatures.
  • The payload shape is described under Webhooks. Update your handler to read data.emailId and the event fields from there.

Field reference

ResendRetransmitNotes
fromfromSame format. The domain must be verified on Retransmit.
to, cc, bccto, cc, bccString or array, up to 50 addresses each.
replyToreplyToreply_to on the HTTP API.
subjectsubjectSame.
html, texthtml, textAt least one is required.
reactnoneRender to a string first. See above.
headersheadersSame shape, up to 20. See Custom headers.
tagstagsSame { name, value } shape, up to 10. Filter by tag in List Emails.
attachmentsattachmentsSame shape: filename plus content or path, and contentId for inline images. Up to 20 files and 30 MB. Not on the batch endpoint, same as Resend. See Attachments.
scheduledAtscheduledAtSame field, with one restriction: Retransmit takes an ISO 8601 instant with an offset, not natural language like "in 1 min". Rescheduling is PATCH /v1/emails/:id and cancelling is POST /v1/emails/:id/cancel, as on Resend. See Schedule Email.
idempotencyKeyidempotencyKeySame Idempotency-Key header, same 24 hour window and 409 codes. Passed as the second argument in both SDKs. See Idempotency.
nonemarketingHosted unsubscribe link and suppression list. See Marketing Email.
nonebounceReasonOn a retrieved email, why a bounce happened, classified from the receiving server’s SMTP response. See Bounce reasons.

Cutting over

  1. Verify your domain on Retransmit while Resend keeps sending.
  2. Deploy the client swap behind a flag or an environment variable.
  3. Point your webhook handler at both providers during the switch. Event names match, so most of the handler is shared.
  4. Move traffic, watch Get Email and the dashboard for delivered events, then remove the Resend key.
Last updated on