Migrate from Resend

A straightforward guide to moving your email infrastructure from Resend to Veil Mail. Both platforms share a modern, developer-first approach, so the migration is minimal.

Overview

Resend and Veil Mail have very similar API designs. If you're already using Resend, you'll find Veil Mail's SDK and REST API immediately familiar. The primary additions Veil Mail brings are automatic PII scanning, built-in CASL compliance, and a broader feature set including campaigns, A/B testing, automation sequences, and RSS feeds.

Most of the migration involves swapping the SDK package and updating a few field names. Your existing email sending logic will remain largely unchanged.

SDK Migration

Replace the resend package with @resonia/veilmail-sdk.

# Remove Resend
npm uninstall resend

# Install Veil Mail
npm install @resonia/veilmail-sdk

Send Email Comparison

Resend

resend.ts
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxxxxxx');

await resend.emails.send({
  from: 'hello@yourdomain.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<h1>Welcome to our platform!</h1>',
});

Veil Mail

veilmail.ts
import { VeilMail } from '@resonia/veilmail-sdk';

const client = new VeilMail('veil_live_xxxxx');

await client.emails.send({
  from: 'hello@yourdomain.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<h1>Welcome to our platform!</h1>',
});

Note: The send call signature is nearly identical. The only change is the constructor and import.

Domain Management Comparison

Resend

resend-domains.ts
// List domains
const domains = await resend.domains.list();

// Add domain
const domain = await resend.domains.create({
  name: 'yourdomain.com',
});

// Verify domain
await resend.domains.verify(domain.id);

Veil Mail

veilmail-domains.ts
// List domains
const domains = await client.domains.list();

// Add domain
const domain = await client.domains.create({
  name: 'yourdomain.com',
});

// Verify domain
await client.domains.verify(domain.id);

API Endpoint Mapping

Resend and Veil Mail endpoints map almost one-to-one. The main difference is the /v1 version prefix and base URL.

Base URL: Resend uses https://api.resend.com, Veil Mail uses https://api.veilmail.xyz

ResendVeil MailNotes
POST /emailsPOST /v1/emailsVery similar payload
GET /emails/:idGET /v1/emails/:idDirect mapping
POST /emails/batchPOST /v1/emails/batchDirect mapping
GET /domainsGET /v1/domainsDirect mapping
POST /audiencesPOST /v1/audiencesDirect mapping
GET /api-keysGET /v1/api-keysDirect mapping

Webhook Migration

Both platforms use similar webhook event structures. Update your event type names to match Veil Mail's namespaced format.

Resend EventVeil Mail Event
email.sentemail.sent
email.deliveredemail.delivered
email.delivery_delayedemail.deferred
email.bouncedemail.bounced
email.complainedemail.complained
email.openedemail.opened
email.clickedemail.clicked

Good news: Most event names are identical. The main difference is email.delivery_delayed becomes email.deferred. Veil Mail also adds additional events like subscriber.unsubscribed and campaign.sent that are not available in Resend.

Veil Mail uses the X-VeilMail-Signature header for webhook verification. Replace your Resend signature verification with the Veil Mail equivalent:

webhook-verify.ts
import crypto from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

// In your webhook handler
const signature = req.headers['x-veilmail-signature'] as string;
const isValid = verifyWebhook(rawBody, signature, process.env.VEILMAIL_WEBHOOK_SECRET!);

React Email Integration

If you're using React Email with Resend, you can continue using your existing React Email components with Veil Mail. Use the @resonia/react-email adapter to render your components to HTML before sending.

npm install @resonia/react-email
react-email.ts
import { VeilMail } from '@resonia/veilmail-sdk';
import { render } from '@resonia/react-email';
import { WelcomeEmail } from './emails/welcome';

const client = new VeilMail('veil_live_xxxxx');

// Render your React Email component to HTML
const html = await render(WelcomeEmail({ name: 'Alice' }));

await client.emails.send({
  from: 'hello@yourdomain.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html,
});

Your existing React Email component files can be used without modification. The @resonia/react-email adapter is a drop-in replacement for @react-email/render.

What You Gain

Migrating from Resend to Veil Mail gives you access to a broader feature set while maintaining the same developer experience you already know.

  • Automatic PII protection -- every email is scanned for sensitive data (SSNs, credit cards, health records) before delivery
  • Built-in CASL compliance -- consent tracking, unsubscribe management, and regulatory compliance tools
  • Campaign A/B testing -- test subject lines, content, and send times to optimize engagement
  • Automation sequences -- build drip campaigns and automated email workflows with branching logic
  • RSS-to-email feeds -- automatically send new content to subscribers when your RSS feed updates
  • Advanced analytics -- detailed delivery, engagement, and audience analytics with exportable reports
  • More SDKs -- official SDKs for Node.js, Python, Go, Ruby, PHP, Java, .NET, Rust, Elixir, Unity, and Unreal Engine