Email is a critical component of modern web applications, used for everything from user onboarding and notifications to password resets and marketing campaigns. However, building and managing a reliable email sending infrastructure can be complex and time-consuming. This is where email API services like Resend come in.
Resend offers a developer-friendly platform designed to simplify the process of sending transactional and marketing emails. It provides robust APIs, detailed analytics, and excellent deliverability, allowing developers to focus on building their applications rather than worrying about email infrastructure.
This comprehensive guide will walk you through everything you need to know to get started with the Resend API, from understanding its core concepts and pricing to integrating it with various popular frameworks and platforms.
Want an integrated, All-in-One platform for your Developer Team to work together with maximum productivity?
Apidog delivers all your demans, and replaces Postman at a much more affordable price!
What is Resend?

Resend is an email API platform built for developers. It aims to provide a superior developer experience compared to older email service providers (ESPs). Key features include:
- Modern API: A clean, RESTful API that's easy to integrate into any application.
- High Deliverability: Focuses on ensuring your emails reach the inbox, not the spam folder, through features like custom domain verification (DKIM, SPF, DMARC), dedicated IPs (as an add-on), and automatic suppression list management.
- Framework Integrations: Offers official SDKs and guides for popular frameworks like Node.js, Next.js, Python, Ruby, PHP, Go, and more.
- React Email Integration: Seamlessly integrates with React Email, allowing you to build beautiful, responsive email templates using React components.
- Webhooks: Provides real-time notifications about email events like delivery, bounces, opens, clicks, and spam complaints.
- Detailed Analytics: Offers insights into email performance through a user-friendly dashboard.
- Developer Focus: Designed with developers in mind, offering clear documentation, helpful SDKs, and tools like test emails for easier development and debugging.
Resend positions itself as a more modern, developer-centric alternative to established players like SendGrid, Mailgun, or AWS SES, focusing on ease of use, reliability, and integrating well with modern web development workflows.
What's Resend Pricing?

Resend offers a tiered pricing structure based on the number of emails sent per month, with separate considerations for transactional and marketing emails (though the pricing page primarily details transactional plans).
Here's a breakdown of their transactional email plans (as of the time of writing):
Free Plan:
- Cost: $0 / month
- Emails: Up to 3,000 emails per month
- Daily Limit: 100 emails per day
- Domains: 1 custom domain
- Data Retention: 1 day
- Support: Ticket Support
- Key Features: RESTful API, SMTP Relay, SDKs, Open/Link Tracking, React Email Integration, Automatic Suppression List, DKIM/SPF/DMARC Authentication, 1 Webhook Endpoint.
- Limitations: No Single Sign-On (SSO), No Dedicated IPs, Limited domains and daily sending.
Pro Plan:
- Cost: $20 / month
- Emails: Up to 50,000 emails per month (with overage charges applying beyond this)
- Daily Limit: No daily limit
- Domains: 10 custom domains
- Data Retention: 3 days
- Support: Ticket Support
- Key Features: All Free plan features, plus SSO, 10 Webhook Endpoints.
- Limitations: No Dedicated IPs included (available as add-on later), No Slack support.
Scale Plan:
- Cost: $90 / month
- Emails: Up to 100,000 emails per month (with overage charges)
- Daily Limit: No daily limit
- Domains: 1,000 custom domains
- Data Retention: 7 days
- Support: Slack & Ticket Support
- Key Features: All Pro plan features, plus Dedicated IP available as an add-on ($30/mo, requires >500 emails/day).
- Limitations: Dedicated IPs are an add-on.
Enterprise Plan:
- Cost: Custom pricing
- Emails: Custom volume
- Daily Limit: No daily limit
- Domains: Flexible
- Data Retention: Flexible
- Support: Priority Support, Urgent Response SLA, Deliverability Expertise
- Key Features: All Scale plan features, plus Dedicated IP Warming, Deliverability Insights, Flexible Webhooks, SSO included.
Key Considerations:
- Overage: Sending more emails than your plan allows will incur additional costs per email.
- Dedicated IPs: Available as an add-on for the Scale and Enterprise plans for an additional monthly fee, recommended for high-volume senders concerned about shared IP reputation.
- Data Retention: The duration for which Resend stores logs and details about your sent emails varies by plan.
- Marketing Emails: The pricing page has a toggle for Marketing Emails, suggesting different plans or pricing structures might apply, but details were focused on transactional emails in the scraped content. Check the Resend website for the most current Marketing Email pricing.
The Free plan is generous enough for small projects or testing purposes. The Pro and Scale plans cater to growing applications with increasing email volumes and feature requirements. The Enterprise plan provides tailored solutions for large-scale operations.
Getting Started with Resend
Before you can send emails, you need to set up your Resend account and configure your sending domain.
1. Sign Up and Create an API Key
- Go to the Resend website and sign up for an account.
- Navigate to the API Keys section in your Resend dashboard (https://resend.com/api-keys).
- Click Create API Key.
- Give your API key a descriptive name (e.g.,
my-app-key
). - Choose the permission level:
- Full access: Allows all API actions (create, delete, get, update resources). Use with caution, typically only needed for backend management tasks.
- Sending access: Only allows sending emails. This is the recommended permission for your application's sending logic. You can optionally restrict this key to send only from a specific verified domain.
- Click Create.
- Important: Resend will show you the API key only once. Copy it immediately and store it securely (e.g., in an environment variable, secrets manager). Do not commit it directly into your codebase.
2. Verify Your Domain
To send emails that appear professional and avoid spam filters, you must verify a domain you own. Sending from unverified domains or default addresses like onboarding@resend.dev
is only suitable for initial testing.
- Go to the Domains section in your Resend dashboard (https://resend.com/domains).
- Click Add Domain and enter the domain you want to send emails from (e.g.,
yourcompany.com
). - Choose your DNS provider from the list or select 'Other'.
- Resend will provide you with DNS records (usually MX, TXT for SPF, and CNAME/TXT for DKIM) that you need to add to your domain's DNS settings.
- SPF (Sender Policy Framework): Specifies which mail servers are authorized to send email on behalf of your domain.
- DKIM (DomainKeys Identified Mail): Adds a digital signature to emails, allowing receiving servers to verify the email hasn't been tampered with and originated from an authorized server.
- Log in to your domain registrar or DNS provider (e.g., GoDaddy, Cloudflare, Namecheap) and add the records provided by Resend.
- DNS changes can take some time to propagate (minutes to hours, sometimes up to 48 hours).
- Once the records are added, go back to the Resend Domains dashboard and click the Verify button next to your domain. Resend will check if the DNS records are set up correctly. Once verified, the status will update, and you can start sending emails from addresses associated with that domain (e.g.,
support@yourcompany.com
,noreply@yourcompany.com
).
3. Sending Test Emails
During development, it's crucial to test email sending without affecting your domain's reputation or sending to real users accidentally. Resend provides special email addresses for testing different scenarios:
- Test Delivered: Send to
delivered@resend.dev
. This simulates a successfully delivered email. - Test Bounced: Send to
bounced@resend.dev
. This simulates a hard bounce (e.g., the recipient address doesn't exist), triggering a bounce event. - Test Marked as Spam: Send to
complained@resend.dev
. This simulates a recipient marking your email as spam, triggering a complaint event.
Using these test addresses allows you to verify your integration and test webhook handlers for bounce and complaint events safely.
Integrating Resend with Frameworks
Resend provides official SDKs and straightforward integration methods for various languages and frameworks. We'll cover some popular examples based on the provided documentation. The core concept usually involves:
- Installing the Resend SDK (if available) or using standard HTTP requests.
- Initializing the Resend client with your API key (loaded securely, usually from environment variables).
- Calling the
emails.send
method (or equivalent) with parameters likefrom
,to
,subject
, andhtml
orreact
.
Sending with Next.js
Next.js is a popular React framework. Resend integrates nicely, especially with React Email.
1. Install:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. Create Email Template (Optional but recommended):Use React Email or create a simple React component for your email body.
// components/email-template.tsx
import * as React from 'react';
interface EmailTemplateProps {
firstName: string;
}
export const EmailTemplate: React.FC<Readonly<EmailTemplateProps>> = ({
firstName,
}) => (
<div>
<h1>Welcome, {firstName}!</h1>
</div>
);
3. Create API Route:Create an API route handler to send the email.
- App Router:
app/api/send/route.ts
- Pages Router:
pages/api/send.ts
// app/api/send/route.ts (App Router Example)
import { EmailTemplate } from '../../../components/email-template'; // Adjust path if needed
import { Resend } from 'resend';
// Ensure RESEND_API_KEY is set in your .env.local
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST() {
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>', // Use your verified domain
to: ['delivered@resend.dev'], // Replace with recipient or test address
subject: 'Hello from Resend and Next.js!',
react: EmailTemplate({ firstName: 'Test' }), // Pass props to your template
// Alternatively, use `html`:
// html: '<strong>It works!</strong>'
});
if (error) {
return Response.json({ error }, { status: 400 });
}
return Response.json(data);
} catch (error) {
return Response.json({ error }, { status: 500 });
}
}
// pages/api/send.ts (Pages Router Example - adapt imports/response)
// import type { NextApiRequest, NextApiResponse } from 'next';
// import { EmailTemplate } from '../../components/EmailTemplate';
// import { Resend } from 'resend';
//
// const resend = new Resend(process.env.RESEND_API_KEY);
//
// export default async (req: NextApiRequest, res: NextApiResponse) => {
// try { // Added try...catch for better error handling
// const { data, error } = await resend.emails.send({
// from: 'Your Name <you@yourverifieddomain.com>',
// to: ['delivered@resend.dev'],
// subject: 'Hello world',
// react: EmailTemplate({ firstName: 'John' }),
// });
//
// if (error) {
// return res.status(400).json(error);
// }
//
// res.status(200).json(data);
// } catch (e) {
// res.status(500).json({ error: 'Internal Server Error' });
// }
// };
4. Trigger:Call this API endpoint from your frontend (e.g., after a form submission) using fetch
or a library like axios
. Remember to replace placeholder values with your actual verified domain and recipient lists.
Sending with Astro
Astro is a modern static site builder that also supports server-side rendering (SSR).
1. Install Resend:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. Install SSR Adapter:Astro needs an SSR adapter to run server-side code on demand. Install one suitable for your deployment target (e.g., @astrojs/node
, @astrojs/vercel
, @astrojs/cloudflare
).
npx astro add node # Example for Node.js adapter
Follow the adapter's setup instructions in your astro.config.mjs
.
3. Add API Key:Store your RESEND_API_KEY
in your .env
file.
4. Create Astro Action:Use Astro Actions (experimental feature as of writing, check Astro docs for current status) or standard API endpoints.
// src/actions/index.ts (Using Astro Actions)
import { ActionError, defineAction, z } from 'astro:actions';
import { Resend } from 'resend';
// Ensure RESEND_API_KEY is available via import.meta.env
const resend = new Resend(import.meta.env.RESEND_API_KEY);
export const server = {
send: defineAction({
// Example: Define input validation if needed
// input: z.object({ email: z.string().email() }),
handler: async (/* { email } - if using input */) => {
try { // Added try...catch
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // Replace with recipient
subject: 'Hello from Resend and Astro!',
html: '<strong>Astro works!</strong>',
// You can also use React templates if you set up React in Astro
// react: <YourAstroCompatibleReactEmail firstName="Astro" />
});
if (error) {
console.error("Resend Error:", error); // Log error
// Throwing ActionError helps Astro handle errors gracefully
throw new ActionError({
code: 'BAD_REQUEST', // Or be more specific based on error
message: error.message || 'Failed to send email',
});
}
return data; // Return success data
} catch (e) {
console.error("Handler Error:", e);
// Re-throw or throw a new ActionError
throw new ActionError({
code: 'INTERNAL_SERVER_ERROR',
message: 'An unexpected error occurred.',
});
}
},
}),
};
// Alternative: API Endpoint (e.g., src/pages/api/send.ts)
// import type { APIRoute } from 'astro';
// import { Resend } from 'resend';
//
// const resend = new Resend(import.meta.env.RESEND_API_KEY);
//
// export const POST: APIRoute = async ({ request }) => {
// // const body = await request.json(); // If data comes from request body
// try {
// const { data, error } = await resend.emails.send({ /* ... email params ... */ });
// if (error) {
// return new Response(JSON.stringify(error), { status: 400 });
// }
// return new Response(JSON.stringify(data), { status: 200 });
// } catch (e) {
// return new Response(JSON.stringify({ message: "Server Error"}), { status: 500 });
// }
// }
5. Trigger:Call the action or endpoint from your Astro components or pages, typically within a form submission handler.
Sending with Bun
Bun is a fast JavaScript runtime with a built-in bundler, transpiler, task runner, and npm client.
1. Install:
bun install resend
2. Create Email Template (Optional):Similar to Next.js, you can create a .tsx
file for your React email template.
// email-template.tsx
import * as React from 'react';
interface EmailTemplateProps {
firstName: string;
}
export const EmailTemplate: React.FC<Readonly<EmailTemplateProps>> = ({
firstName,
}) => (
<div>
<h1>Welcome, {firstName}!</h1>
</div>
);
3. Create Bun Server Script:Create a script (e.g., index.tsx
) to run a simple HTTP server using Bun.
// index.tsx
import { Resend } from 'resend';
import { EmailTemplate } from './email-template'; // Assuming it's in the same dir
// Load API key from environment variables
const resendApiKey = process.env.RESEND_API_KEY;
if (!resendApiKey) {
console.error("Error: RESEND_API_KEY environment variable not set.");
process.exit(1); // Exit if key is missing
}
const resend = new Resend(resendApiKey);
const server = Bun.serve({
port: 3000,
async fetch(req) { // Added 'req' argument
// Optional: Check request method, path, etc.
// if (new URL(req.url).pathname !== '/send') {
// return new Response("Not Found", { status: 404 });
// }
// if (req.method !== 'POST') {
// return new Response("Method Not Allowed", { status: 405 });
// }
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend and Bun!',
react: EmailTemplate({ firstName: 'Bun User' }),
// Or use html: '<strong>Bun works!</strong>'
});
if (error) {
console.error("Resend Error:", error);
// Return a proper JSON error response
return new Response(JSON.stringify({ error: error.message || 'Failed to send email' }), {
status: 500, // Or 400 depending on error type
headers: { 'Content-Type': 'application/json' },
});
}
// Return success response
return new Response(JSON.stringify(data), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (e) {
console.error("Server Error:", e);
return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
},
error(error) { // Added basic error handler for the server itself
return new Response(`<pre>${error}\\\\\\\\n${error.stack}</pre>`, {
headers: { "Content-Type": "text/html" },
});
},
});
console.log(`Listening on <http://localhost>:${server.port} ...`);
4. Run:Start the server using RESEND_API_KEY=your_api_key bun run index.tsx
. Accessing http://localhost:3000
(or triggering the specific route/method you defined) will send the email.
Sending with Nuxt
Nuxt is a popular Vue.js framework.
1. Install:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. Create Server Route:Nuxt uses a server/
directory for backend logic. Create a file like server/api/send.post.ts
(the .post
indicates it handles POST requests).
// server/api/send.post.ts
import { Resend } from 'resend';
// Access API Key securely (e.g., via runtimeConfig in nuxt.config.ts)
// See: <https://nuxt.com/docs/guide/going-further/runtime-config>
const config = useRuntimeConfig();
const resend = new Resend(config.resendApiKey); // Assuming key is set in runtime config
export default defineEventHandler(async (event) => {
// Optional: Read body if data comes from request
// const body = await readBody(event);
try {
const data = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend and Nuxt!',
html: '<strong>Nuxt works!</strong>',
// You can integrate Vue email templates (e.g., using vue-email)
// See: <https://github.com/Dave136/vue-email>
});
// Nuxt 3 automatically handles returning the data as JSON
return data;
} catch (error: any) { // Catch specific error types if possible
console.error("Resend Error:", error);
// Throw an error that Nuxt can handle, setting the status code
throw createError({
statusCode: 400, // Or 500
statusMessage: 'Failed to send email',
data: error // Optionally include error details
});
}
});
// In your nuxt.config.ts, define runtimeConfig:
// export default defineNuxtConfig({
// runtimeConfig: {
// resendApiKey: process.env.NUXT_RESEND_API_KEY, // Server-side only
// public: {
// // Public keys accessible on client-side
// }
// }
// })
// And set NUXT_RESEND_API_KEY in your .env
3. Trigger:Call the /api/send
endpoint (using POST method) from your Nuxt pages or components using $fetch
or useFetch
.
Sending with Vercel Functions
Vercel Functions are serverless functions that integrate seamlessly with Next.js or can be used standalone. The Next.js example above already demonstrates usage within a Vercel environment. If using Vercel Functions without Next.js (e.g., with a static site generator or another framework deployed on Vercel), the approach is similar:
1. Create Function:Create a file in the api/
directory of your project (e.g., api/send.ts
).
// api/send.ts (Example for standard Vercel Function)
import type { VercelRequest, VercelResponse } from '@vercel/node';
import { Resend } from 'resend'; // You might need to install resend
// Ensure RESEND_API_KEY is set as a Vercel Environment Variable
const resendApiKey = process.env.RESEND_API_KEY;
if (!resendApiKey) {
console.error("RESEND_API_KEY is not set");
// Don't proceed if the key is missing in production
}
const resend = new Resend(resendApiKey);
export default async function handler(
request: VercelRequest,
response: VercelResponse,
) {
// Recommended: Check for POST method
if (request.method !== 'POST') {
return response.status(405).json({ message: 'Method Not Allowed' });
}
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend & Vercel Functions!',
html: '<strong>It works on Vercel!</strong>',
// React templates can be used if your function bundles React
});
if (error) {
console.error('Resend Error:', error);
return response.status(400).json(error);
}
return response.status(200).json(data);
} catch (e) {
console.error('Handler Error:', e);
return response.status(500).json({ message: 'Internal Server Error' });
}
}
2. Configure Environment Variable:Add your RESEND_API_KEY
as an Environment Variable in your Vercel project settings.
3. Deploy:Deploy your project using the Vercel CLI (vercel
) or Git integration.
4. Trigger:Make a POST request to the deployed function URL (e.g., https://your-project.vercel.app/api/send
).
Sending with Supabase Edge Functions
Supabase Edge Functions run on Deno Deploy, close to your users. They use Deno and standard Web APIs like fetch
. Resend doesn't have an official Deno SDK yet, so you use fetch
directly.
1. Create Supabase Function:Use the Supabase CLI:
supabase functions new resend-email-sender # Choose a name
cd supabase/functions/resend-email-sender
2. Edit Handler:Modify the generated index.ts
file.
// supabase/functions/resend-email-sender/index.ts
import { serve } from "<https://deno.land/std@0.177.0/http/server.ts>"; // Use appropriate std version
// Access API Key securely via Supabase Edge Function environment variables
const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY');
// Basic request handler
const handler = async (_request: Request): Promise<Response> => {
if (!RESEND_API_KEY) {
console.error("RESEND_API_KEY environment variable not set.");
return new Response(JSON.stringify({ error: "Server configuration error" }), {
status: 500, headers: { 'Content-Type': 'application/json' }
});
}
// Optional: Check _request method, headers, or body if needed
try {
const res = await fetch('<https://api.resend.com/emails>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${RESEND_API_KEY}` // Use the key here
},
body: JSON.stringify({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // Replace recipient
subject: 'Hello from Resend & Supabase Edge!',
html: '<strong>It works! Edge Functions are cool.</strong>',
// Note: Sending React components directly isn't feasible here
// without a build step in the edge function to render them to HTML.
// Send pre-rendered HTML or plain text.
})
});
// Handle potential non-OK responses from Resend API
if (!res.ok) {
const errorData = await res.json().catch(() => ({ message: 'Failed to parse Resend error response' }));
console.error("Resend API Error:", res.status, errorData);
return new Response(JSON.stringify({ error: 'Failed to send email via Resend', details: errorData }), {
status: res.status, // Forward Resend's status code
headers: { 'Content-Type': 'application/json' },
});
}
// Parse successful response
const data = await res.json();
// Return success response
return new Response(JSON.stringify(data), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (error) {
console.error("Edge Function Error:", error);
return new Response(JSON.stringify({ error: 'Internal Server Error in Edge Function' }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
};
// Start the server
serve(handler);
console.log("Supabase Edge Function 'resend-email-sender' is running...");
3. Set Environment Variable:Set the RESEND_API_KEY
locally using supabase secrets set RESEND_API_KEY your_actual_key
and also set it in your Supabase project's Function settings for deployment.
4. Deploy & Invoke:
# Test locally (optional)
supabase functions serve resend-email-sender --no-verify-jwt
# Deploy
supabase functions deploy resend-email-sender --no-verify-jwt
Invoke the function using its URL, typically via a Supabase client library call from your frontend or another backend service.
Sending with Cloudflare Workers
Cloudflare Workers are serverless functions running on Cloudflare's edge network. Resend's Node.js SDK can often work in Workers environments with appropriate bundling.
1. Setup Worker Project:Initialize a Worker project, often using npm create cloudflare
. Ensure it's set up for modules and bundling (e.g., using Wrangler with Webpack or esbuild).
2. Install Resend:
npm install resend
# or yarn/pnpm
3. Create Email Template (Optional):If using React, create your template file (.tsx
).
4. Edit Worker Script:Modify your main worker file (e.g., src/index.ts
or src/index.tsx
if using React).
// src/index.tsx (Example using React)
import { Resend } from 'resend';
// Assuming you have a React template component
import { EmailTemplate } from './emails/email-template'; // Adjust path
// Define the expected environment variables for type safety
export interface Env {
RESEND_API_KEY: string;
}
export default {
async fetch(
request: Request,
env: Env, // Access environment variables via 'env'
ctx: ExecutionContext
): Promise<Response> {
// Instantiate Resend using the API key from environment variables
const resend = new Resend(env.RESEND_API_KEY);
// Optional: Check request method, URL path, etc.
// Example: Only allow POST requests to a specific path
// const url = new URL(request.url);
// if (url.pathname !== '/send-email' || request.method !== 'POST') {
// return new Response('Not Found or Method Not Allowed', { status: 404 });
// }
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // Replace recipient
subject: 'Hello from Resend & Cloudflare Workers!',
// Use the React component if applicable
react: <EmailTemplate firstName="Worker User" />,
// Or use HTML
// html: '<strong>It works from the Edge!</strong>',
});
if (error) {
console.error("Resend Error:", JSON.stringify(error));
return Response.json({ error: 'Failed to send email via Resend' }, { status: 400 });
}
return Response.json(data);
} catch (e) {
console.error("Worker Error:", e);
// Log the error stack if possible
if (e instanceof Error) {
console.error(e.stack);
}
return Response.json({ error: 'Internal Server Error in Worker' }, { status: 500 });
}
},
} // satisfies ExportedHandler<Env>; // Optional: Use satisfies for better type checking
5. Configure Environment Variable:Set your RESEND_API_KEY
as a secret for your Worker using Wrangler:
npx wrangler secret put RESEND_API_KEY
# Paste your key when prompted
6. Deploy:
npx wrangler deploy # Or 'wrangler dev' for local testing
Invoke the Worker using its assigned URL.
Sending with AWS Lambda
Scraping for the AWS Lambda documentation page timed out, so this section is based on general principles.
Sending emails from AWS Lambda using Resend follows a similar pattern:
1. Setup Lambda Function:Create a Lambda function using your preferred runtime (Node.js is common and works well with the Resend SDK). Ensure your Lambda has internet access (e.g., configured within a VPC with a NAT Gateway or using default VPC settings that allow egress).
2. Install Resend SDK:Include resend
in your function's deployment package (e.g., in package.json
and run npm install
before zipping or use Lambda Layers).
3. Store API Key Securely:Use AWS Secrets Manager or AWS Systems Manager Parameter Store to store your RESEND_API_KEY
. Grant your Lambda function's execution role permission to read this secret. Do not hardcode the key in the Lambda function code.
4. Write Lambda Handler Code (Node.js Example):
// lambda_function.js (Node.js example)
const { Resend } = require('resend');
// AWS SDK clients (if getting key from Secrets Manager/Parameter Store)
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); // V3 SDK
let resend; // Initialize outside handler for potential reuse
async function getApiKey() {
// Replace with your secret name/ARN and region
const secretName = "your/resend/api/key/secret";
const client = new SecretsManagerClient({ region: "your-region" });
try {
const command = new GetSecretValueCommand({ SecretId: secretName });
const response = await client.send(command);
if ('SecretString' in response) {
// Assuming the secret stores the key directly or as JSON like {"apiKey": "re_..."}
const secret = JSON.parse(response.SecretString);
return secret.apiKey; // Adjust parsing based on how you stored it
}
throw new Error("API Key not found in secret string");
} catch (error) {
console.error("Error retrieving API Key from Secrets Manager:", error);
throw error; // Re-throw to signal failure
}
}
exports.handler = async (event, context) => {
// Optional: Parse event data if needed (e.g., from API Gateway trigger)
// const body = JSON.parse(event.body || '{}');
// const recipient = body.to;
try {
if (!resend) {
const apiKey = await getApiKey();
if (!apiKey) {
return { statusCode: 500, body: JSON.stringify({ message: "API Key configuration error" }) };
}
resend = new Resend(apiKey);
}
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // Use recipient from event or fixed value
subject: 'Hello from Resend & AWS Lambda!',
html: '<strong>Lambda email sent successfully!</strong>',
// React requires a build step or server-side rendering setup within Lambda
});
if (error) {
console.error('Resend Error:', error);
return {
statusCode: 400, // Or appropriate status based on error
body: JSON.stringify(error),
};
}
return {
statusCode: 200,
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
};
} catch (e) {
console.error('Lambda Handler Error:', e);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Internal Server Error' }),
};
}
};
5. Configure Trigger:Set up a trigger for your Lambda function (e.g., API Gateway for HTTP requests, SQS queue, EventBridge event).
6. Deploy:Deploy your Lambda function and its dependencies.
Using React Email with Resend
A major advantage of Resend is its seamless integration with React Email. React Email allows you to build beautiful, responsive email templates using standard React components and syntax.
Benefits:
- Component-Based: Structure emails like web apps using reusable components.
- Type Safety: Use TypeScript for more robust templates.
- Local Development: Develop and preview emails locally in your browser.
- No Complex Templating Languages: Avoid proprietary or complex email templating syntax.
Setup (Based on React Email Docs - may vary slightly):
Install: Add react-email
and its core components to your project. You'll likely need resend
as well if sending through them.
npm install react-email @react-email/components resend
# or yarn/pnpm
Create Email Templates: Create .tsx
files for your emails, usually in a dedicated emails/
directory.
// emails/welcome.tsx
import { Html, Button, Text } from '@react-email/components';
import * as React from 'react';
interface WelcomeEmailProps {
name: string;
signupLink: string;
}
export const WelcomeEmail: React.FC<Readonly<WelcomeEmailProps>> = ({ name, signupLink }) => (
<Html>
<Text>Hello {name},</Text>
<Text>Welcome aboard! Click the button below to get started.</Text>
<Button href={signupLink}>Complete Signup</Button>
</Html>
);
export default WelcomeEmail; // Default export is often helpful
Integrate with Sending Logic: In your backend API route or serverless function, import the email component and pass it to Resend's react
option.
// Example in a Next.js API Route (app/api/send-welcome/route.ts)
import { Resend } from 'resend';
import WelcomeEmail from '../../../emails/welcome'; // Adjust path
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(request: Request) {
try {
const body = await request.json(); // Assuming { email: '...', name: '...' } in body
const signupUrl = "<https://yoursite.com/signup-step2>"; // Example URL
const { data, error } = await resend.emails.send({
from: 'Your App <welcome@yourverifieddomain.com>',
to: [body.email],
subject: 'Welcome to Our Platform!',
// Pass the React component directly
react: WelcomeEmail({ name: body.name, signupLink: signupUrl }),
});
if (error) {
return Response.json({ error }, { status: 400 });
}
return Response.json(data);
} catch (error) {
return Response.json({ error }, { status: 500 });
}
}
Resend (and React Email's build process if used standalone) handles rendering the React component to email-safe HTML behind the scenes. This significantly improves the developer experience for creating and maintaining email templates.
Conclusion
Resend offers a modern, developer-focused solution for sending emails. Its clean API, excellent framework integrations (especially with React Email), focus on deliverability, and helpful features like test emails and webhooks make it a compelling choice for applications of all sizes.
By following the steps outlined in this guide—setting up your account, verifying your domain, choosing the right integration method for your framework, and leveraging tools like React Email—you can quickly and reliably integrate robust email functionality into your projects. Remember to always handle API keys securely and monitor your sending activity through the Resend dashboard and webhooks to ensure optimal deliverability and user experience.
Want an integrated, All-in-One platform for your Developer Team to work together with maximum productivity?
Apidog delivers all your demans, and replaces Postman at a much more affordable price!