name: sendgrid description: Sends transactional and marketing emails with SendGrid API. Use when integrating email delivery in Node.js applications with templates, analytics, and high deliverability.
SendGrid Email API
Email delivery platform with high deliverability, templates, and analytics. Part of Twilio.
Quick Start
npm install @sendgrid/mail
Setup
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
Send Basic Email
const msg = {
to: 'recipient@example.com',
from: 'sender@example.com', // Must be verified sender
subject: 'Hello from SendGrid',
text: 'Plain text content',
html: '<strong>HTML content</strong>',
};
await sgMail.send(msg);
Email Options
Full Message Object
const msg = {
// Recipients
to: 'single@example.com',
// Or multiple
to: ['one@example.com', 'two@example.com'],
// Or with names
to: [
{ email: 'one@example.com', name: 'User One' },
{ email: 'two@example.com', name: 'User Two' },
],
// Sender
from: {
email: 'sender@example.com',
name: 'My App',
},
// Reply-to (optional)
replyTo: 'support@example.com',
// Subject
subject: 'Your order has shipped',
// Content
text: 'Plain text version',
html: '<h1>HTML version</h1>',
// CC and BCC
cc: 'cc@example.com',
bcc: 'bcc@example.com',
// Categories for analytics
categories: ['transactional', 'order-confirmation'],
// Custom headers
headers: {
'X-Custom-Header': 'value',
},
// Send at specific time
sendAt: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
// Attachments
attachments: [
{
content: base64EncodedContent,
filename: 'invoice.pdf',
type: 'application/pdf',
disposition: 'attachment',
},
],
};
await sgMail.send(msg);
Dynamic Templates
Create templates in SendGrid dashboard with handlebars syntax.
const msg = {
to: 'recipient@example.com',
from: 'sender@example.com',
templateId: 'd-xxxxxxxxxxxxxxxxxxxxxxxx',
dynamicTemplateData: {
name: 'John',
orderNumber: '12345',
items: [
{ name: 'Product 1', price: 29.99 },
{ name: 'Product 2', price: 49.99 },
],
total: 79.98,
},
};
await sgMail.send(msg);
Template Variables
In your SendGrid template:
<h1>Hello {{name}}!</h1>
<p>Your order #{{orderNumber}} has shipped.</p>
<table>
{{#each items}}
<tr>
<td>{{this.name}}</td>
<td>${{this.price}}</td>
</tr>
{{/each}}
<tr>
<td><strong>Total</strong></td>
<td><strong>${{total}}</strong></td>
</tr>
</table>
Multiple Recipients
Same Email to Multiple
const msg = {
to: ['user1@example.com', 'user2@example.com'],
from: 'sender@example.com',
subject: 'Newsletter',
html: '<p>Content for all</p>',
};
await sgMail.send(msg);
Personalized Emails (sendMultiple)
const msgs = [
{
to: 'user1@example.com',
from: 'sender@example.com',
subject: 'Hello User 1',
html: '<p>Content for User 1</p>',
},
{
to: 'user2@example.com',
from: 'sender@example.com',
subject: 'Hello User 2',
html: '<p>Content for User 2</p>',
},
];
await sgMail.send(msgs); // Sends in batch
Personalizations (Most Efficient)
const msg = {
from: 'sender@example.com',
subject: 'Order Update',
templateId: 'd-xxxxxx',
personalizations: [
{
to: 'user1@example.com',
dynamicTemplateData: {
name: 'Alice',
orderNumber: '001',
},
},
{
to: 'user2@example.com',
dynamicTemplateData: {
name: 'Bob',
orderNumber: '002',
},
},
],
};
await sgMail.send(msg);
Attachments
import fs from 'fs';
const msg = {
to: 'recipient@example.com',
from: 'sender@example.com',
subject: 'Your invoice',
html: '<p>Please find your invoice attached.</p>',
attachments: [
{
content: fs.readFileSync('./invoice.pdf').toString('base64'),
filename: 'invoice.pdf',
type: 'application/pdf',
disposition: 'attachment',
},
{
content: fs.readFileSync('./logo.png').toString('base64'),
filename: 'logo.png',
type: 'image/png',
disposition: 'inline',
contentId: 'logo', // Reference in HTML as <img" alt="sendgrid image">
},
],
};
await sgMail.send(msg);
Error Handling
try {
await sgMail.send(msg);
console.log('Email sent successfully');
} catch (error) {
console.error('Error sending email:', error);
if (error.response) {
console.error('Status code:', error.code);
console.error('Body:', error.response.body);
console.error('Headers:', error.response.headers);
}
}
Common Errors
| Code | Description |
|---|---|
| 400 | Bad request (check payload) |
| 401 | Unauthorized (check API key) |
| 403 | Forbidden (sender not verified) |
| 429 | Rate limit exceeded |
| 500 | SendGrid server error |
Webhooks (Event Tracking)
Configure in SendGrid dashboard to receive events.
// API route to receive webhooks
export async function POST(request) {
const events = await request.json();
for (const event of events) {
switch (event.event) {
case 'delivered':
console.log('Email delivered to:', event.email);
break;
case 'open':
console.log('Email opened by:', event.email);
break;
case 'click':
console.log('Link clicked:', event.url);
break;
case 'bounce':
console.log('Bounced:', event.email, event.reason);
// Remove from mailing list
break;
case 'spam_report':
console.log('Spam report from:', event.email);
// Unsubscribe user
break;
}
}
return new Response('OK');
}
Full API Client
For advanced operations beyond sending.
npm install @sendgrid/client
import Client from '@sendgrid/client';
const client = new Client();
client.setApiKey(process.env.SENDGRID_API_KEY);
// Get email statistics
const [response, body] = await client.request({
method: 'GET',
url: '/v3/stats',
qs: {
start_date: '2024-01-01',
end_date: '2024-01-31',
},
});
console.log(body);
Next.js API Route
// app/api/send-email/route.ts
import { NextResponse } from 'next/server';
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY!);
export async function POST(request: Request) {
const { to, subject, html } = await request.json();
try {
await sgMail.send({
to,
from: process.env.SENDGRID_FROM_EMAIL!,
subject,
html,
});
return NextResponse.json({ success: true });
} catch (error) {
console.error('SendGrid error:', error);
return NextResponse.json(
{ error: 'Failed to send email' },
{ status: 500 }
);
}
}
With React Email
import sgMail from '@sendgrid/mail';
import { render } from '@react-email/components';
import WelcomeEmail from './emails/welcome';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
async function sendWelcomeEmail(user) {
const html = await render(WelcomeEmail({
name: user.name,
actionUrl: `https://myapp.com/onboarding`,
}));
await sgMail.send({
to: user.email,
from: 'welcome@myapp.com',
subject: `Welcome to MyApp, ${user.name}!`,
html,
});
}
Environment Variables
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxxx
SENDGRID_FROM_EMAIL=noreply@yourdomain.com
Sender Verification
Before sending, verify your sender identity:
- Single Sender Verification - Verify individual email addresses
- Domain Authentication - Verify entire domain (recommended for production)
Configure in SendGrid Dashboard > Settings > Sender Authentication.
Best Practices
- Verify your domain - Improves deliverability
- Use templates - Easier to maintain and update
- Handle bounces - Remove invalid addresses
- Monitor events - Track delivery and engagement
- Rate limit - Don't exceed plan limits
- Use categories - For analytics segmentation
- Include unsubscribe - Required for marketing emails
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
GitHub Stars
3
GitHub Forks
0
Created
Jan 2026
Last Updated
5 months ago
tools
tools productivity tools
Related Skills
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!