Resend logo

resend

Modern email API for developers

$ npx docs2skills add resend-email-api
SKILL.md

Resend

Modern email API for developers

What this skill does

Resend is a developer-first email API that simplifies transactional email sending. It provides a clean, modern alternative to traditional SMTP services with built-in deliverability optimizations, webhooks for tracking, and support for multiple programming languages.

Unlike legacy email services, Resend focuses on developer experience with intuitive APIs, comprehensive SDKs, and features like email domain verification, activity monitoring, and event webhooks. It's designed for applications that need reliable transactional emails like user onboarding, password resets, notifications, and marketing automation.

Prerequisites

  • Resend account and API key from https://resend.com/api-keys
  • Verified domain (for production use)
  • Node.js 16+, Python 3.7+, PHP 8.0+, or other supported runtime
  • Internet connection for API calls

Quick start

Node.js

npm install resend
import { Resend } from 'resend';

const resend = new Resend('re_123456789');

const { data, error } = await resend.emails.send({
  from: 'Acme <onboarding@resend.dev>',
  to: ['delivered@resend.dev'],
  subject: 'Hello World',
  html: '<strong>It works!</strong>',
});

if (error) {
  console.error(error);
} else {
  console.log(data);
}

Python

pip install resend
import resend

resend.api_key = "re_123456789"

params = {
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "subject": "Hello World",
    "html": "<strong>It works!</strong>"
}

email = resend.Emails.send(params)
print(email)

Core concepts

API Key Authentication: All requests use Bearer token authentication with your API key.

Email Objects: Emails are structured with required fields (from, to, subject) and optional fields (html, text, attachments, headers).

Domain Verification: Production emails require verified domains to ensure deliverability and avoid spam filters.

Webhooks: Real-time notifications for email events (delivered, opened, clicked, bounced) sent to your endpoints.

Rate Limits: API calls are rate-limited based on your plan tier.

Key API surface

Node.js SDK

// Send email
resend.emails.send(emailObject)

// Get email by ID
resend.emails.get(emailId)

// Send batch emails
resend.batch.send([emailObject1, emailObject2])

// Domain management
resend.domains.create({ name: 'example.com' })
resend.domains.verify(domainId)
resend.domains.list()

// Contact management
resend.contacts.create({ email: 'user@example.com', audienceId })
resend.contacts.list(audienceId)

// Audience management
resend.audiences.create({ name: 'Newsletter' })

Python SDK

# Send email
resend.Emails.send(params)

# Get email
resend.Emails.get(email_id)

# Domain operations
resend.Domains.create({"name": "example.com"})
resend.Domains.verify(domain_id)

REST API

# Send email
POST https://api.resend.com/emails

# Get email
GET https://api.resend.com/emails/{email_id}

Common patterns

HTML email with attachments

await resend.emails.send({
  from: 'team@company.com',
  to: 'user@example.com',
  subject: 'Invoice #12345',
  html: `
    <h1>Your Invoice</h1>
    <p>Please find your invoice attached.</p>
  `,
  attachments: [{
    filename: 'invoice.pdf',
    content: fs.readFileSync('invoice.pdf'),
  }]
});

Bulk email sending

const emails = users.map(user => ({
  from: 'newsletter@company.com',
  to: user.email,
  subject: `Hi ${user.name}!`,
  html: `<p>Personal message for ${user.name}</p>`
}));

const { data } = await resend.batch.send(emails);

Email templates with variables

await resend.emails.send({
  from: 'noreply@company.com',
  to: user.email,
  subject: 'Welcome aboard!',
  html: `
    <h1>Welcome ${user.name}!</h1>
    <p>Your account ${user.email} is ready.</p>
    <a href="${process.env.APP_URL}/verify?token=${user.token}">
      Verify Email
    </a>
  `
});

Webhook handling (Express)

app.post('/webhooks/resend', (req, res) => {
  const { type, data } = req.body;
  
  switch (type) {
    case 'email.delivered':
      console.log(`Email ${data.email_id} delivered`);
      break;
    case 'email.bounced':
      console.log(`Email ${data.email_id} bounced`);
      break;
  }
  
  res.status(200).send('OK');
});

Configuration

Environment variables

RESEND_API_KEY=re_your_api_key_here

Domain setup

  1. Add domain in Resend dashboard
  2. Add DNS records (SPF, DKIM, DMARC)
  3. Verify domain status
  4. Use verified domain in 'from' field

Webhook configuration

// Configure webhook endpoint in Resend dashboard
// Handle these events: delivered, bounced, complained, opened, clicked

Best practices

  • Always use verified domains for production emails
  • Handle both data and error responses from API calls
  • Implement exponential backoff for failed requests
  • Use environment variables for API keys, never hardcode
  • Validate email addresses before sending
  • Implement webhook endpoints for delivery tracking
  • Use batch sending for multiple emails to improve performance
  • Include both HTML and text versions for better compatibility
  • Set appropriate reply-to addresses for transactional emails
  • Monitor your sending reputation through the Resend dashboard

Gotchas and common mistakes

Unverified domains: Emails from unverified domains may be rejected or marked as spam. Always verify domains in production.

Rate limiting: Free tier has strict rate limits. Implement proper error handling for 429 responses.

Email format validation: Resend validates email formats strictly. Malformed addresses will cause API errors.

Attachment size limits: Attachments are limited to 40MB total per email.

Webhook verification: Resend doesn't provide webhook signature verification yet - implement IP allowlisting.

API key exposure: Never commit API keys to version control. Use environment variables.

Bounce handling: Implement webhook handlers for bounces to maintain sender reputation.

HTML encoding: Properly escape user data in HTML templates to prevent XSS.

Subject line limits: Subject lines over 78 characters may be truncated by email clients.

Testing vs production: Use different API keys and domains for development and production environments.

Async/await errors: Always wrap Resend calls in try-catch blocks or handle promise rejections.

Batch limits: Batch sending is limited to 100 emails per request.