Migration Guides
Migrate from SendGrid
Step-by-step guide to migrate from SendGrid to send0.
Overview
SendGrid's API has grown complex over the years. send0 provides a cleaner, modern API with simpler authentication and better developer experience.
1. Install the SDK
Replace @sendgrid/mail with send0:
# Before
npm install @sendgrid/mail
# After
npm install send0Python:
# Before
pip install sendgrid
# After
pip install send0Go:
# Before
go get github.com/sendgrid/sendgrid-go
# After
go get github.com/send0/send0-go2. Update the client
TypeScript:
// Before (SendGrid)
import sgMail from '@sendgrid/mail';
sgMail.setApiKey('SG.xxx');
// After (send0)
import { Send0 } from 'send0';
const send0 = new Send0('sk_live_...');Python:
# Before (SendGrid)
from sendgrid import SendGridAPIClient
sg = SendGridAPIClient("SG.xxx")
# After (send0)
from send0 import Send0
client = Send0("sk_live_...")Go:
// Before (SendGrid)
client := sendgrid.NewSendClient("SG.xxx")
// After (send0)
client := send0.New("sk_live_...")3. Update send calls
SendGrid's personalizations pattern is replaced by a simpler flat structure.
TypeScript:
// Before (SendGrid)
await sgMail.send({
to: 'user@example.com',
from: 'hello@acme.com',
subject: 'Welcome',
html: '<p>Hello</p>',
categories: ['onboarding'],
customArgs: { user_id: '123' },
});
// After (send0)
await send0.emails.send({
from: 'hello@acme.com',
to: 'user@example.com',
subject: 'Welcome',
html: '<p>Hello</p>',
tags: { category: 'onboarding' },
metadata: { user_id: '123' },
});Python:
# Before (SendGrid)
from sendgrid.helpers.mail import Mail
message = Mail(
from_email="hello@acme.com",
to_emails="user@example.com",
subject="Welcome",
html_content="<p>Hello</p>",
)
sg.send(message)
# After (send0)
client.emails.send(
from_address="hello@acme.com",
to="user@example.com",
subject="Welcome",
html="<p>Hello</p>",
)Go:
// Before (SendGrid)
from := mail.NewEmail("Acme", "hello@acme.com")
to := mail.NewEmail("User", "user@example.com")
message := mail.NewSingleEmail(from, "Welcome", to, "Hello", "<p>Hello</p>")
client.Send(message)
// After (send0)
client.Emails.Send(ctx, &send0.SendEmailParams{
From: "Acme <hello@acme.com>",
To: []string{"user@example.com"},
Subject: "Welcome",
HTML: "<p>Hello</p>",
})4. Batch sending
SendGrid uses personalizations for per-recipient data. send0 uses a dedicated batch endpoint.
// Before (SendGrid)
await sgMail.send({
personalizations: [
{ to: 'jane@example.com', dynamicTemplateData: { name: 'Jane' } },
{ to: 'john@example.com', dynamicTemplateData: { name: 'John' } },
],
from: 'hello@acme.com',
templateId: 'd-xxx',
});
// After (send0)
await send0.emails.batch({
from: 'hello@acme.com',
subject: 'Monthly Update',
template: 'tmpl_monthly',
recipients: [
{ to: 'jane@example.com', variables: { name: 'Jane' } },
{ to: 'john@example.com', variables: { name: 'John' } },
],
});5. Templates
SendGrid uses dynamic templates with Handlebars. send0 supports both server-side templates with {{variable}} syntax and JSX email components.
// Server-side template
const template = await send0.templates.create({
name: 'welcome',
subject: 'Welcome, {{name}}!',
html: '<h1>Hello {{name}}</h1><p>Welcome to {{company}}.</p>',
});
// Use in a send
await send0.emails.send({
from: 'hello@acme.com',
to: 'user@example.com',
subject: 'Welcome!',
template: template.id,
data: { name: 'Jane', company: 'Acme' },
});6. Webhook migration
Replace SendGrid's Event Webhook with send0's webhook endpoints.
// send0 webhook verification
import { Send0 } from 'send0';
const event = Send0.webhooks.verify(
requestBody,
requestHeaders,
'whsec_...',
);
switch (event.type) {
case 'email.delivered':
// handle delivery
break;
case 'email.bounced':
// handle bounce
break;
}7. Event type mapping
| SendGrid event | send0 event |
|---|---|
processed | email.queued |
delivered | email.delivered |
open | email.opened |
click | email.clicked |
bounce | email.bounced |
spamreport | email.complained |
dropped | email.failed |
8. Concept mapping
| SendGrid concept | send0 equivalent |
|---|---|
API key (SG.xxx) | API key (sk_live_...) |
| Marketing Contacts | Contacts with tags |
| Dynamic Templates | Templates ({{variable}} syntax) |
| Sender Authentication | Domain verification (DKIM + SPF) |
| Personalizations | Batch recipients |
| Categories | Tags |
| Custom Args | Metadata |
| Suppressions | Suppression list |
| IP Access Management | IP allowlists on API keys |
| Subuser / API Key Permissions | Restricted keys with scopes |
9. Feature comparison
| Feature | SendGrid | send0 |
|---|---|---|
| Transactional email | Yes | Yes |
| Marketing email | Yes (complex setup) | Yes (simple category: 'marketing') |
| Batch send | Via personalizations | Dedicated /v1/emails/batch endpoint |
| Contacts | Yes (complex) | Yes (simple CRUD + batch upsert) |
| Templates | Dynamic templates (Handlebars) | {{variable}} + JSX components |
| Webhooks | Event Webhook (no signatures) | HMAC-SHA256 signed webhooks |
| Test-mode API keys | No | Yes (sk_test_… never delivers) |
| CLI | No | Yes (send0 emails send, events tail, …) |
| API key scopes | Yes (complex) | Yes (simple scope strings) |
| Audit log | No | Yes |
| Free tier | 100/day | 3,000/month |
| Pricing model | Complex tiers | Simple per-send pricing |