---
title: "Migrate from Resend to OpenEmail"
description: "Move from Resend to OpenEmail: every field mapped, a code converter for Node.js, Python, Ruby and cURL, and the webhook events side by side."
url: "https://openemail.uk/migrate/resend"
---

[All migrations](https://openemail.uk/migrate.md)

Migrate from Resend

# Move from Resend to OpenEmail.

Point the Resend SDK at OpenEmail and keep your code, or convert it to the OpenEmail SDK. Audiences, contacts, templates and webhooks come across with one key.

[Convert your code](https://openemail.uk/migrate/resend#convert) [Open mail](https://openemail.uk/mail/inbox) [Get Started](https://openemail.uk/signup.md)

## The same email, written both ways.

One message with a reply-to address and a tag, sent through Resend and then through OpenEmail.

```
1import { Resend } from 'resend'2 3const resend = new Resend(process.env.RESEND_API_KEY)4 5const { data, error } = await resend.emails.send({6  from: 'Acme <billing@acme.com>',7  to: ['ada@example.com'],8  replyTo: 'support@acme.com',9  subject: 'Your invoice is ready',10  html: '<p>Thanks for your order.</p>',11  tags: [{ name: 'category', value: 'invoice' }],12})13 14if (error) {15  console.error(error.message)16} else {17  console.log(data.id)18}
```

```
1import { init, openemail } from '@openemail/sdk'2 3init({ apiKey: process.env.OPENEMAIL_API_KEY })4 5try {6  const email = await openemail.emails.send({7    from: 'Acme <billing@acme.com>',8    to: ['ada@example.com'],9    replyTo: 'support@acme.com',10    subject: 'Your invoice is ready',11    html: '<p>Thanks for your order.</p>',12    tags: { category: 'invoice' },13  })14  console.log(email.id)15} catch (error) {16  console.error(error.message)17}
```

## Field by field, what goes where.

Each option Resend takes, and its place in OpenEmail.

| Resend | OpenEmail | Notes |
| --- | --- | --- |
| `from, to, cc, bcc, subject, html, text` | `from, to, cc, bcc, subject, html, text` | Same names and the same meaning. |
| `reply_to` | `replyTo` | One address per message. |
| `tags: [{ name, value }]` | `tags: { name: value }` | Up to 10 key and value pairs. |
| `react` | `html` | Render the component to HTML first. |
| `attachments[].path` | `attachments[].content` | Fetch the file and pass its bytes. |
| `scheduled_at` | `scheduledAt` | A date, an ISO time or a duration. |
| `Idempotency-Key` | `idempotencyKey` | Same meaning, 255 characters at most. |
| `batch.send` | `emails.sendBatch` | Up to 100 emails, each sent on its own. |
| `contacts.create({ audienceId })` | `contacts.create({ audienceIds })` | One name field, several audiences. |

Converter

## Paste your Resend code, get it back on OpenEmail.

Pick where the code comes from and its language. Recognised keys are removed in your browser, and nothing you paste is kept.

From Resend

Your OpenEmail code appears here

Paste a file, or load an example, then convert.

0 of 12,000 characters Recognised keys are removed before sending.

## Coming from Resend? Change two lines.

Point the Resend SDK at OpenEmail and keep your code, then bring contacts, templates and webhooks across.

[Read the Resend guide](https://openemail.uk/docs/knowledge/developers/switch-from-resend.md)

Two differences: a message takes one reply-to address, and an inline image referenced by content id arrives as an ordinary attachment.

Your Resend SDK code stays as it is

```
+RESEND_BASE_URL=https://api.openemail.uk/compat/resend+RESEND_API_KEY=oe_live_…
```

Answered in Resend's own shapes and error names

Bring the rest with one key

- Suppressions
- Audiences
- Contacts
- Templates
- Webhooks

## Bring the rest with one key.

Paste a Resend key, check what is there and start the import. Data moves across, and domains and keys arrive as a checklist, so nothing is left behind.

## Move from Resend

Move your setup over from Resend.

Resend API key

Use a full-access Resend key. Revoke it afterwards.

re\_••••••••••••••••

Recommended

Suppressions

214 found

Bounced, complained and blocked addresses keep their reason.

Audiences

3 found

Each segment becomes an audience.

Contacts

8,532 found

Only subscribed contacts arrive, with their names.

Templates

12 found

Arrive as HTML templates with variables declared.

Webhooks

2 found

Added switched off, since signing differs here.

Domains checklist

2 found

Lists each domain with records to publish.

API keys checklist

3 found

Lists each key so you can recreate it.

Keep your code

Set these two variables to send through OpenEmail.

.env

```
RESEND_BASE_URL=https://api.openemail.uk/compat/resendRESEND_API_KEY=oe_live_…
```

What to bring across

## Webhook events, renamed.

Each Resend event and the OpenEmail event that replaces it. Every request carries one event, signed.

| Resend | OpenEmail |
| --- | --- |
| `email.sent` | `email.sent` |
| `email.delivered` | `email.delivered` |
| `email.delivery_delayed` | `email.delivery_delayed` |
| `email.bounced` | `email.bounced` |
| `email.complained` | `email.complained` |
| `email.opened` | `email.opened` |
| `email.clicked` | `email.clicked` |
| `email.failed` | `email.failed` |

## Moving from Resend, answered.

## Moving from somewhere else?

Every guide has the same converter, field map and checklist.

- [SendGrid Migration guide Personalizations, dynamic templates and event webhooks.](https://openemail.uk/migrate/sendgrid.md)
- [Postmark Migration guide Server tokens, message streams and templates.](https://openemail.uk/migrate/postmark.md)
- [Mailgun Migration guide Domains, o: options and v: variables.](https://openemail.uk/migrate/mailgun.md)
- [Amazon SES Migration guide SESv2 calls, configuration sets and SNS events.](https://openemail.uk/migrate/amazon-ses.md)

## Converted? Create the key it reads.

A workspace takes a minute. Add your domain, create an API key and set OPENEMAIL\_API\_KEY.

[Open mail](https://openemail.uk/mail/inbox) [Get Started](https://openemail.uk/signup.md)[Read the SDK docs](https://openemail.uk/docs/sdk.md)
