send0
Migration Guides

Migrate from Resend

Step-by-step guide to migrate from Resend to send0.

Overview

send0's API is designed to be familiar to Resend users. Most concepts map 1:1 — the migration is straightforward.

1. Install the SDK

Replace resend with send0:

# Before
npm install resend

# After
npm install send0

Python:

# Before
pip install resend

# After
pip install send0

2. Update the client

TypeScript:

// Before (Resend)
import { Resend } from 'resend';
const resend = new Resend('re_...');

// After (send0)
import { Send0 } from 'send0';
const send0 = new Send0('sk_live_...');

Python:

# Before (Resend)
import resend
resend.api_key = "re_..."

# After (send0)
from send0 import Send0
client = Send0("sk_live_...")

3. Update send calls

The send API is nearly identical. Key differences:

Resendsend0Notes
resend.emails.send()send0.emails.send()Same interface
react parametertemplate parameterUse template IDs or JSX components
scheduledAt (ISO string)scheduledAt (Date object in TS)send0 accepts Date objects
tags (array of {name, value})tags (object {key: value})Simpler key-value format
No batch endpointsend0.emails.batch()send0 supports batch sends natively

TypeScript:

// Before (Resend)
const email = await resend.emails.send({
  from: 'hello@acme.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<p>Hello</p>',
  tags: [{ name: 'category', value: 'onboarding' }],
});

// After (send0)
const email = await send0.emails.send({
  from: 'hello@acme.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<p>Hello</p>',
  tags: { category: 'onboarding' },
});

Python:

# Before (Resend)
email = resend.Emails.send({
    "from": "hello@acme.com",
    "to": "user@example.com",
    "subject": "Welcome!",
    "html": "<p>Hello</p>",
})

# After (send0)
email = client.emails.send(
    from_address="hello@acme.com",
    to="user@example.com",
    subject="Welcome!",
    html="<p>Hello</p>",
)

4. Update webhook verification

TypeScript:

// Before (Resend) — uses Svix
import { Webhook } from 'svix';
const wh = new Webhook(secret);
const event = wh.verify(body, headers);

// After (send0) — built-in
import { Send0 } from 'send0';
const event = Send0.webhooks.verify(body, headers, secret);

Python:

# After (send0)
from send0 import Webhooks
event = Webhooks.verify(body, headers, secret)

5. Update domain verification

The domain verification flow is similar. send0 requires DKIM, SPF, and optionally DMARC records.

// Add domain
const domain = await send0.domains.create({ domain: 'mail.acme.com' });

// Configure DNS records from domain.dns_records
// Then verify
const result = await send0.domains.verify(domain.id);

6. Concept mapping

Resend conceptsend0 equivalent
API key (re_...)API key (sk_live_..., sk_test_..., sk_restr_...)
AudiencesContacts with tags
DomainsDomains
EmailsEmails
Webhooks (Svix)Webhooks (native HMAC-SHA256)
React Emailsend0 JSX components (send0/components)

7. Feature comparison

FeatureResendsend0
Transactional emailYesYes
Marketing emailNoYes (with daily cap + one-click unsubscribe)
Batch sendYes (100 max)Yes (100 max)
Contacts/audiencesYesYes
TemplatesNo (React only)Yes (server-side + JSX)
Webhook verificationSvixNative HMAC-SHA256
Test-mode API keysNoYes (sk_test_… never delivers)
CLINoYes (send0 emails send, events tail, …)
IP allowlistsNoYes
Restricted API keysNoYes (scoped permissions)
Audit logNoYes
Free tier3,000/month3,000/month