Skip to content
Docs

Switching from Resend

Our API takes the same requests as Resend’s, so Resend’s official Node.js SDK works against it unchanged. Moving is a new API key and one base URL.

Before you switch

  1. Add the domain you send from under Domains in the dashboard. Our three DKIM records (…._domainkey) sit beside Resend’s resend._domainkey, so both can sign while you move, and those three alone verify the domain with us.
  2. Leave Resend’s send. records until you have moved. Both services use send. your domain for bounces, each pointing at its own Amazon SES region. Keep Resend’s MX there until all your sending has moved, then replace it with ours. Until then we use Amazon SES’s own bounce address, and DKIM still passes DMARC. “Add to Cloudflare” leaves Resend’s records alone, and shows that MX as one for you to decide.
  3. Make an API key under API keys. A full-access key does everything below; a sending key can only send.
  4. Bring your suppression list. Under Suppressions, import the addresses that bounced, complained or unsubscribed with Resend — a CSV export, or one address a line — so this account never sends to them.

A new account starts in the sandbox: it sends only to its own team until we have approved it. See the limits.

Point the SDK here

Set your new key and our base URL where Resend’s SDK looks for them. With both in the environment, new Resend() needs no change at all:

Or give them in code, before the first request:

The answer is the SDK’s own: data with the email’s id, or error with a name, a message and a statusCode.

What works

Our test suite runs Resend’s SDK, version 6.32.1, against this API on every change. These are the calls it covers.

CallWhat it does here
emails.sendEvery field the SDK sends: from, to, cc, bcc, replyTo, subject, html, text, headers, tags, scheduledAt and attachments — content as a Buffer or base64, contentType, and contentId for inline images — and the idempotencyKey option.
batch.sendUp to 100 emails, queued all together or not at all.
emails.getThe email, its status and its latest event.
emails.listThe newest first, with limit.
emails.updateMoves an email still waiting to its new scheduledAt.
emails.cancelCancels an email still waiting.
domains.list, domains.getYour domains and their status.
webhooks.verifyChecks our webhook deliveries with your endpoint’s signing secret. Our email events are email.sent, email.delivered, email.delivery_delayed, email.bounced, email.complained and email.failed; the webhooks guide shows the payload.

What is different

If you useHere
scheduledAtAn ISO 8601 date and time with its zone, at most 72 hours ahead. Words like “in 1 hour” are refused.
Attachments by URL (path)Not supported: send the file itself in content.
batch.send with batchValidation: permissiveRefused. A batch is queued whole or not at all — the SDK’s default.
emails.list with after or beforeRefused. Ask for a larger limit, or page with the HTTP API’s cursor.
Custom headersX-* (but not X-SES-*), List-Unsubscribe, List-Unsubscribe-Post, List-Id, In-Reply-To, References and Auto-Submitted.
Templates, contacts, segments, broadcasts, topics, receivingNot offered. A call to one answers not_found or validation_error.
Open and click trackingNot offered.
A new accountStarts in the sandbox, sending only to its own team, until we have approved it.

Error names

Code that checks error.statusCode needs no change. Code that checks error.name should look for ours; the errors page explains each.

Resend’s SDKHereStatus
missing_api_key, invalid_api_keyunauthorized401
restricted_api_key, invalid_accessforbidden403
invalid_from_addressdomain_not_verified, validation_error403, 422
validation_error, missing_required_field, invalid_parameter, invalid_attachment, invalid_idempotency_key, invalid_idempotent_requestvalidation_error422
rate_limit_exceededrate_limited429
daily_quota_exceeded, monthly_quota_exceededquota_exceeded429
not_foundnot_found404
application_error, internal_server_errorinternal_error500

account_paused (403) is ours alone: sending is paused on the account, and the dashboard says why.

Other languages

We test Resend’s Node.js SDK only. For another language, call the HTTP API directly — the quickstart has curl, Node, Python and PHP — or write to hello@mydomainshub.com and tell us which SDK you use.

Resend is a trademark of its owner. MyDomainsHub is not affiliated with Resend.