Migrate from SendGrid to Resend
Overview
Resend is a modern email platform for developers. This skill covers migrating SendGrid integrations to Resend across all supported SDKs.
Automated tool: resend.com/migrate/sendgrid — paste SendGrid code and get Resend code instantly.
Detection Patterns
Code is SendGrid if it contains any of: @sendgrid/mail, sendgrid, SendGrid, SENDGRID, sgMail, sg.client, sendgrid-ruby, sendgrid-go, sendgrid-java, sendgrid-php
Migration Checklist
Key Differences at a Glance
| Aspect |
SendGrid |
Resend |
| API endpoint |
https://api.sendgrid.com/v3/mail/send |
https://api.resend.com/emails |
| Auth header |
Authorization: Bearer $SENDGRID_API_KEY |
Authorization: Bearer $RESEND_API_KEY |
| Batch send |
sgMail.sendMultiple() |
resend.batch.send() |
| Response |
[response, body] |
{ data, error } |
| Idempotency |
Not supported |
Idempotency-Key header or SDK option |
| Rate limit info |
Error only |
IETF-standard response headers |
| Rust SDK |
No official SDK |
resend-rs available |
| Templates |
Dynamic templates (templateId) |
React Email components or html |
| Tracking |
Per-email trackingSettings |
Configured per-domain in dashboard |
| Unsubscribe groups |
asm field |
Resend Topics (topic_id) |
| IP pools |
ipPoolName field |
Account-level in dashboard |
Quick Reference
| Reference |
Use When |
| SDK Examples |
Converting code for Node.js, Python, Ruby, Go, PHP, Java, .NET, Elixir, cURL |
| SMTP |
Updating SMTP hostname, port, credentials |
| Webhooks |
Mapping SendGrid event types to Resend event types |
| Feature Mapping |
Templates, tracking, unsubscribe groups, idempotency |
Dashboard Concepts
| SendGrid |
Resend |
| Sender Authentication |
Domains page |
| Activity |
Emails page |
| Dashboard (stats) |
Metrics page |
| Event Webhook |
Webhooks page |
Common Mistakes
| Mistake |
Fix |
asm has "no equivalent" in Resend |
It does — use topic_id field + Resend Topics. See Feature Mapping |
Webhook unsubscribe maps to email.unsubscribed |
That event doesn't exist. Use contact.updated. See Webhooks |
sendAt: unixTimestamp copied over |
Resend uses ISO 8601 string: scheduledAt: new Date(...).toISOString() |
Expecting [response, body] from resend.emails.send() |
Resend returns { data, error } |
| Looking for a CLI migration tool |
The tool is a web UI: resend.com/migrate/sendgrid — no CLI |
sgMail.sendMultiple() replaced by passing array to to field |
Wrong — to array sends one email to multiple recipients. resend.batch.send() sends multiple different emails in one call |
dropped SendGrid event has no Resend equivalent |
Monitor email.bounced and email.delivery_delayed instead. See Webhooks |
| Resend SMTP only supports ports 465 and 587 |
Resend also supports 2465 (SMTPS) and 2587 (STARTTLS) as alternatives. See SMTP |
| Forgot to rename env var |
SENDGRID_API_KEY → RESEND_API_KEY |
Resources
1---2name: migrate-sendgrid3description: Use when migrating SendGrid email integration to Resend - detects @sendgrid/mail, sgMail, sendgrid-ruby, sendgrid-go, sendgrid-java, sendgrid-php, or SENDGRID_API_KEY patterns.4license: MIT5---67# Migrate from SendGrid to Resend89## Overview1011Resend is a modern email platform for developers. This skill covers migrating SendGrid integrations to Resend across all supported SDKs.1213**Automated tool:** [resend.com/migrate/sendgrid](https://resend.com/migrate/sendgrid) — paste SendGrid code and get Resend code instantly.1415## Detection Patterns1617Code is SendGrid if it contains any of: `@sendgrid/mail`, `sendgrid`, `SendGrid`, `SENDGRID`, `sgMail`, `sg.client`, `sendgrid-ruby`, `sendgrid-go`, `sendgrid-java`, `sendgrid-php`1819## Migration Checklist2021- [ ] Verify domain in [Resend Domains](https://resend.com/domains) (SPF/DKIM/DMARC)22- [ ] Create API key at [resend.com/api-keys](https://resend.com/api-keys)23- [ ] Replace env var: `SENDGRID_API_KEY` → `RESEND_API_KEY`24- [ ] Replace SDK (see [SDK Examples](./references/sdk-examples.md))25- [ ] Map webhook events (see [Webhooks](./references/webhooks.md))26- [ ] Update SMTP config if used (see [SMTP](./references/smtp.md))27- [ ] Review feature differences (see [Feature Mapping](./references/feature-mapping.md))2829## Key Differences at a Glance3031| Aspect | SendGrid | Resend |32|--------|----------|--------|33| API endpoint | `https://api.sendgrid.com/v3/mail/send` | `https://api.resend.com/emails` |34| Auth header | `Authorization: Bearer $SENDGRID_API_KEY` | `Authorization: Bearer $RESEND_API_KEY` |35| Batch send | `sgMail.sendMultiple()` | `resend.batch.send()` |36| Response | `[response, body]` | `{ data, error }` |37| Idempotency | Not supported | `Idempotency-Key` header or SDK option |38| Rate limit info | Error only | IETF-standard response headers |39| Rust SDK | No official SDK | `resend-rs` available |40| Templates | Dynamic templates (`templateId`) | React Email components or `html` |41| Tracking | Per-email `trackingSettings` | Configured per-domain in dashboard |42| Unsubscribe groups | `asm` field | Resend Topics (`topic_id`) |43| IP pools | `ipPoolName` field | Account-level in dashboard |4445## Quick Reference4647| Reference | Use When |48|-----------|----------|49| [SDK Examples](./references/sdk-examples.md) | Converting code for Node.js, Python, Ruby, Go, PHP, Java, .NET, Elixir, cURL |50| [SMTP](./references/smtp.md) | Updating SMTP hostname, port, credentials |51| [Webhooks](./references/webhooks.md) | Mapping SendGrid event types to Resend event types |52| [Feature Mapping](./references/feature-mapping.md) | Templates, tracking, unsubscribe groups, idempotency |5354## Dashboard Concepts5556| SendGrid | Resend |57|----------|--------|58| Sender Authentication | Domains page |59| Activity | Emails page |60| Dashboard (stats) | Metrics page |61| Event Webhook | Webhooks page |6263## Common Mistakes6465| Mistake | Fix |66|---------|-----|67| `asm` has "no equivalent" in Resend | It does — use `topic_id` field + Resend Topics. See [Feature Mapping](./references/feature-mapping.md) |68| Webhook `unsubscribe` maps to `email.unsubscribed` | That event doesn't exist. Use `contact.updated`. See [Webhooks](./references/webhooks.md) |69| `sendAt: unixTimestamp` copied over | Resend uses ISO 8601 string: `scheduledAt: new Date(...).toISOString()` |70| Expecting `[response, body]` from `resend.emails.send()` | Resend returns `{ data, error }` |71| Looking for a CLI migration tool | The tool is a web UI: [resend.com/migrate/sendgrid](https://resend.com/migrate/sendgrid) — no CLI |72| `sgMail.sendMultiple()` replaced by passing array to `to` field | Wrong — `to` array sends one email to multiple recipients. `resend.batch.send()` sends multiple different emails in one call |73| `dropped` SendGrid event has no Resend equivalent | Monitor `email.bounced` and `email.delivery_delayed` instead. See [Webhooks](./references/webhooks.md) |74| Resend SMTP only supports ports 465 and 587 | Resend also supports 2465 (SMTPS) and 2587 (STARTTLS) as alternatives. See [SMTP](./references/smtp.md) |75| Forgot to rename env var | `SENDGRID_API_KEY` → `RESEND_API_KEY` |7677## Resources7879- [Full migration guide](https://resend.com/migrate/sendgrid)80- [Resend API reference](https://resend.com/docs/api-reference)81- [React Email](https://react.email) — component-based email templates82- [Resend Broadcasts](https://resend.com/broadcasts) — for marketing/newsletter campaigns