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.devCreate 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.
Resend
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.
Resend
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:
renderis exported by@react-email/components, which you already have if you use React Email. If you want a smaller dependency, install@react-email/renderand import it from there.- Since React Email 1.0,
renderreturns a promise. On older versions it returns the string directly, so drop theawait. { plainText: true }produces the text body from the same component. It is optional, but sending bothhtmlandtexthelps 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-timestampandretransmit-signatureheaders, 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.emailIdand the event fields from there.
Field reference
| Resend | Retransmit | Notes |
|---|---|---|
from | from | Same format. The domain must be verified on Retransmit. |
to, cc, bcc | to, cc, bcc | String or array, up to 50 addresses each. |
replyTo | replyTo | reply_to on the HTTP API. |
subject | subject | Same. |
html, text | html, text | At least one is required. |
react | none | Render to a string first. See above. |
headers | headers | Same shape, up to 20. See Custom headers. |
tags | tags | Same { name, value } shape, up to 10. Filter by tag in List Emails. |
attachments | attachments | Same 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. |
scheduledAt | scheduledAt | Same 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. |
idempotencyKey | idempotencyKey | Same Idempotency-Key header, same 24 hour window and 409 codes. Passed as the second argument in both SDKs. See Idempotency. |
| none | marketing | Hosted unsubscribe link and suppression list. See Marketing Email. |
| none | bounceReason | On a retrieved email, why a bounce happened, classified from the receiving server’s SMTP response. See Bounce reasons. |
Cutting over
- Verify your domain on Retransmit while Resend keeps sending.
- Deploy the client swap behind a flag or an environment variable.
- Point your webhook handler at both providers during the switch. Event names match, so most of the handler is shared.
- Move traffic, watch Get Email and the dashboard for
deliveredevents, then remove the Resend key.