resend/resend-node

Resend's Official Node.js SDK

TypeScript

966

806 commits

updated Oct 16, 2026

See the code

README

nodejs-og

Quickstart Docs

Framework guides

Next.js - Remix - Nuxt - Express - RedwoodJS - Hono - Bun - Astro

Resend Node.js SDK

Node.js library for the Resend API.

Install

npm install resend
# or
yarn add resend

Examples

Send email with:

Setup

First, you need to get an API key, which is available in the Resend Dashboard.

import { Resend } from 'resend';
const resend = new Resend('re_xxxx...xxxxxx');

Usage

Send your first email:

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  text: 'it works!',
});

console.log(`Email ${data.id} has been sent`);

[!NOTE]
In order to send from your own domain, you will first need to verify your domain in the Resend Dashboard.

Send email using HTML

Send an email custom HTML content:

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  html: '<strong>it works!</strong>',
});

console.log(`Email ${data.id} with custom HTML content has been sent.`);

Send email using React

Start by creating your email template as a React component.

import React from 'react';

export default function EmailTemplate({ firstName, product }) {
  return (
    <div>
      <h1>Welcome, {firstName}!</h1>
      <p>Thanks for trying {product}. We’re thrilled to have you on board.</p>
    </div>
  );
}

Then import the template component and pass it to the react property.

import EmailTemplate from '../components/EmailTemplate';

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  react: <EmailTemplate firstName="John" product="MyApp" />,
});

console.log(`Email ${data.id} with a React template has been sent`);

[!NOTE] If you're sending emails from a file that doesn't have JSX transpilation set up (e.g., in a .js/.ts file instead of JSX/TSX), use React's jsx runtime function instead of passing the component as JSX:

import { jsx } from 'react/jsx-runtime'
import EmailTemplate from '../components/EmailTemplate';

await resend.emails.send({
 from: '[email protected]',
 to: '[email protected]',
 replyTo: '[email protected]',
 subject: 'hello world',
 react: jsx(EmailTemplate, { firstName:"John", product:"MyApp" }),
});

Request options

Every method takes request options as its last argument. Use signal to cancel a request or set a timeout, and headers to add request headers:

const controller = new AbortController();
await resend.emails.send({ ... }, { signal: controller.signal });

// With a timeout (Node.js 18+) and a custom header
await resend.emails.list(
  { limit: 50 },
  { signal: AbortSignal.timeout(5000), headers: { 'X-Trace-Id': traceId } },
);

An aborted request returns a network-failure error with a null status code. To tell a cancel apart from a real failure, check the status code and signal.aborted, and do not match on the error message:

const signal = AbortSignal.timeout(5000);
const { error } = await resend.emails.list({}, { signal });

if (error?.statusCode === null && signal.aborted) {
  // The request was cancelled or timed out.
}

When a method has an optional argument before the request options, pass undefined in its place:

await resend.broadcasts.send(broadcastId, undefined, { signal });

A chained publish() sends a separate request, so it takes its own options:

await resend.templates
  .create({ name: 'welcome', html: '<p>Hi</p>' }, { signal })
  .publish({ signal });

Inboxes

Create an inbox and list its threads:

const { data: inbox } = await resend.inboxes.create({
  emailAddress: '[email protected]',
  name: 'support',
});

const { data: threads } = await resend.inboxes.threads.list({
  inboxId: inbox.id,
  folders: ['inbox'],
});

Every inbox method also accepts the inbox email address instead of its ID:

const { data: threads } = await resend.inboxes.threads.list({
  emailAddress: '[email protected]',
  folders: ['inbox'],
});

await resend.inboxes.update('[email protected]', { fromName: 'Support' });

License

MIT License

resend/resend-node

Resend's Official Node.js SDK

TypeScript

966

806 commits

updated Oct 16, 2026

See the code

README

nodejs-og

Quickstart Docs

Framework guides

Next.js - Remix - Nuxt - Express - RedwoodJS - Hono - Bun - Astro

Resend Node.js SDK

Node.js library for the Resend API.

Install

npm install resend
# or
yarn add resend

Examples

Send email with:

Setup

First, you need to get an API key, which is available in the Resend Dashboard.

import { Resend } from 'resend';
const resend = new Resend('re_xxxx...xxxxxx');

Usage

Send your first email:

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  text: 'it works!',
});

console.log(`Email ${data.id} has been sent`);

[!NOTE]
In order to send from your own domain, you will first need to verify your domain in the Resend Dashboard.

Send email using HTML

Send an email custom HTML content:

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  html: '<strong>it works!</strong>',
});

console.log(`Email ${data.id} with custom HTML content has been sent.`);

Send email using React

Start by creating your email template as a React component.

import React from 'react';

export default function EmailTemplate({ firstName, product }) {
  return (
    <div>
      <h1>Welcome, {firstName}!</h1>
      <p>Thanks for trying {product}. We’re thrilled to have you on board.</p>
    </div>
  );
}

Then import the template component and pass it to the react property.

import EmailTemplate from '../components/EmailTemplate';

const { data } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  replyTo: '[email protected]',
  subject: 'hello world',
  react: <EmailTemplate firstName="John" product="MyApp" />,
});

console.log(`Email ${data.id} with a React template has been sent`);

[!NOTE] If you're sending emails from a file that doesn't have JSX transpilation set up (e.g., in a .js/.ts file instead of JSX/TSX), use React's jsx runtime function instead of passing the component as JSX:

import { jsx } from 'react/jsx-runtime'
import EmailTemplate from '../components/EmailTemplate';

await resend.emails.send({
 from: '[email protected]',
 to: '[email protected]',
 replyTo: '[email protected]',
 subject: 'hello world',
 react: jsx(EmailTemplate, { firstName:"John", product:"MyApp" }),
});

Request options

Every method takes request options as its last argument. Use signal to cancel a request or set a timeout, and headers to add request headers:

const controller = new AbortController();
await resend.emails.send({ ... }, { signal: controller.signal });

// With a timeout (Node.js 18+) and a custom header
await resend.emails.list(
  { limit: 50 },
  { signal: AbortSignal.timeout(5000), headers: { 'X-Trace-Id': traceId } },
);

An aborted request returns a network-failure error with a null status code. To tell a cancel apart from a real failure, check the status code and signal.aborted, and do not match on the error message:

const signal = AbortSignal.timeout(5000);
const { error } = await resend.emails.list({}, { signal });

if (error?.statusCode === null && signal.aborted) {
  // The request was cancelled or timed out.
}

When a method has an optional argument before the request options, pass undefined in its place:

await resend.broadcasts.send(broadcastId, undefined, { signal });

A chained publish() sends a separate request, so it takes its own options:

await resend.templates
  .create({ name: 'welcome', html: '<p>Hi</p>' }, { signal })
  .publish({ signal });

Inboxes

Create an inbox and list its threads:

const { data: inbox } = await resend.inboxes.create({
  emailAddress: '[email protected]',
  name: 'support',
});

const { data: threads } = await resend.inboxes.threads.list({
  inboxId: inbox.id,
  folders: ['inbox'],
});

Every inbox method also accepts the inbox email address instead of its ID:

const { data: threads } = await resend.inboxes.threads.list({
  emailAddress: '[email protected]',
  folders: ['inbox'],
});

await resend.inboxes.update('[email protected]', { fromName: 'Support' });

License

MIT License

Project health

Latest release

6.34.1 · Oct 16, 2026

Releases this year

53

Significant stargazers

Amila Welihinda

1,468 followers · starred Jan 2023

Bruno Lemos

1,184 followers · starred Mar 2026

Phil Nash

1,059 followers · starred Sep 2026

Kenzo Wada

52 followers · starred Nov 2025