Sendr Docs
Guides

Migrating from Resend

Side-by-side comparison of Resend and Sendr endpoints to help you migrate.

Sendr's API is intentionally similar to Resend's. Most migrations take under an hour.

Package swap

# Remove Resend SDK
npm remove resend

# Install Sendr SDK
npm install sendr

Initialization

// Before (Resend)
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

// After (Sendr)
import { Sendr } from "sendr";
const sendr = new Sendr(process.env.SENDR_API_KEY);

Sending emails

The core send call is nearly identical:

// Before (Resend)
const { data, error } = await resend.emails.send({
  from: "hello@acme.com",
  to: "user@example.com",
  subject: "Hello",
  html: "<p>Hello!</p>",
});

// After (Sendr)
const email = await sendr.emails.send({
  from: "hello@acme.com",
  to: "user@example.com",
  subject: "Hello",
  html: "<p>Hello!</p>",
});

Key differences:

  • Sendr throws errors instead of returning { data, error } — wrap in try/catch
  • Sendr returns the email object directly (not nested in data)

Error handling

// Before (Resend)
const { data, error } = await resend.emails.send(params);
if (error) {
  console.error(error.name, error.message);
}

// After (Sendr)
import { ApiError, RateLimitError, AuthenticationError } from "sendr";
try {
  const email = await sendr.emails.send(params);
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Bad API key");
  } else if (error instanceof RateLimitError) {
    await sleep(error.retryAfter * 1000);
  } else if (error instanceof ApiError) {
    console.error(error.statusCode, error.code, error.message);
  }
}

REST API endpoint mapping

FeatureResendSendr
Send emailPOST /emailsPOST /v1/emails
Get emailGET /emails/:idGET /v1/emails/:id
Update emailPATCH /emails/:id
Cancel emailPOST /emails/:id/cancelDELETE /v1/emails/:id
List emailsGET /emailsGET /v1/emails
Send batchPOST /emails/batchPOST /v1/emails/batch
Create domainPOST /domainsPOST /v1/domains
List domainsGET /domainsGET /v1/domains
Get domainGET /domains/:idGET /v1/domains/:id
Verify domainPOST /domains/:id/verifyPOST /v1/domains/:id/verify
Delete domainDELETE /domains/:idDELETE /v1/domains/:id
Create API keyPOST /api-keysPOST /v1/api-keys
List API keysGET /api-keysGET /v1/api-keys
Delete API keyDELETE /api-keys/:idDELETE /v1/api-keys/:id
Create webhookPOST /v1/webhooks
Get webhookGET /v1/webhooks/:id
List webhooksGET /v1/webhooks

All Sendr endpoints are prefixed with /v1/.

Environment variable rename

# .env
# Before
RESEND_API_KEY=re_abc123

# After
SENDR_API_KEY=sndr_live_abc123

React Email compatibility

Sendr is fully compatible with React Email components. No changes needed:

import { render } from "@react-email/render";
import WelcomeEmail from "./emails/welcome";

const html = await render(<WelcomeEmail name="Alice" />);

await sendr.emails.send({
  from: "hello@acme.com",
  to: "alice@example.com",
  subject: "Welcome!",
  html, // React Email rendered HTML works as-is
});

Features available on Sendr but not Resend

  • Marketing emailsPOST /v1/emails/marketing with automatic List-Unsubscribe headers
  • Campaigns — broadcast to contact lists with scheduling and analytics
  • Audiences & Contacts — built-in subscriber management
  • Test mode — test-mode API keys capture emails to a Test Inbox
  • Overage billing — continue sending beyond monthly quota instead of hard cutoff
  • Analytics — built-in delivery stats, open/click rates, and benchmarks

Webhook event name differences

EventResendSendr
Deliveredemail.deliveredemail.delivered
Bouncedemail.bouncedemail.bounced
Openedemail.openedemail.opened
Clickedemail.clickedemail.clicked
Complainedemail.complainedemail.complained

Webhook event names are identical — no changes needed if you're already processing Resend events.

Checklist

  • Replace resend package with sendr
  • Update import from Resend to Sendr
  • Change RESEND_API_KEY to SENDR_API_KEY
  • Prefix REST API URLs with /v1/
  • Update error handling from { data, error } pattern to try/catch
  • Create API keys in Sendr dashboard
  • Verify sending domains in Sendr dashboard
  • Update webhook endpoints (if any) — event names unchanged

On this page