Resend migration guide

Migrate from Resend when you need more than sending

Postscale keeps the modern developer experience and adds SMTP relay, full inbound routing rules, masked addresses, DMARC reporting, and migration-safe webhooks.

Migration scope

  • Convert Resend emails.send payloads to POST /v1/send.
  • Use SMTP relay for systems that cannot call a REST API.
  • Move receiving flows to inbound aliases and signed webhooks.
  • Preserve tags, headers, reply-to, and metadata in the send payload.

What changes when you move

ResendPostscaleMigration note
emails.sendPOST /v1/sendMap html/text to html_body/text_body and keep tags as Postscale tags.
emails.batchPOST /v1/send/batchBatch sends remain independent per message with per-item results.
ReceivingInbound Email APIPostscale delivers parsed inbound email via signed webhooks and stores messages for retrieval.
TemplatesPostscale templatesUse template slugs or keep rendering React Email HTML in your app.
WebhooksPostscale webhooksSubscribe endpoint by endpoint and verify HMAC signatures.

Cut over in controlled steps

1

Mirror DNS

Add Postscale verification, DKIM, return-path, and optional MX records while the old provider keeps sending.

2

Convert code

Swap API credentials and normalize the send payload. Keep the old provider path behind a feature flag for rollback.

3

Move state

Import suppressions and template HTML, then configure delivery, bounce, complaint, and inbound webhooks.

4

Ramp traffic

Start at 10 percent, watch bounces and complaints by ISP, then increase volume as warming limits allow.

Send call conversion

Resend
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({
  from: "Acme <alerts@example.com>",
  to: ["user@example.com"],
  subject: "Welcome",
  html: "<p>Hello from Acme</p>",
  tags: [{ name: "flow", value: "onboarding" }],
});
Postscale
await fetch("https://api.postscale.io/v1/send", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.POSTSCALE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    from: "Acme <alerts@example.com>",
    to: ["user@example.com"],
    subject: "Welcome",
    html_body: "<p>Hello from Acme</p>",
    tags: ["onboarding"],
  }),
});

Production checklist

Lower DNS TTL to 300 seconds at least 24 hours before cutover.
Keep both DKIM selectors published during the transition.
Import hard bounces, complaints, unsubscribes, and manual suppressions before the first production send.
Run webhook handlers in dual-shape mode until all old-provider events have drained.
Send seed tests to Gmail, Outlook, Yahoo, iCloud, and a corporate Microsoft 365 tenant.
Cut over early in the week and avoid final traffic moves on Friday.
Monitor delivery, bounce, deferred, and complaint rates by ISP after each traffic increase.
Keep the old account active until delayed events and user replies have stopped arriving.

Frequently asked questions

Why migrate from Resend if the send API is simple?

Teams usually move when they need SMTP relay, richer inbound routing, masked addresses, DMARC reporting, or EU/EEA-hosted primary service data in the same platform.

Do Resend receiving webhooks map directly?

The flow maps directly, but Postscale can route through aliases and inbound rules before dispatching a signed webhook.

Can I keep my current template system?

Yes. Render HTML in your app exactly as before, or move templates into Postscale when you want template preview and API-managed reuse.